/* ===========================================================================
   BCH360 — Bryan's Cake House
   Dressed from the shop's own hiring poster: a strong red band across the top
   carrying the pattern, gold for the small labels on it, brown for everything
   that is read, and white paper underneath.
   Red is the BAND, never the text — because red inside the page is still
   reserved for money that needs attention, and a page painted red everywhere
   would say nothing when a figure turns red.
   =========================================================================== */

:root{
  --ground:#F4EDEA; --panel:#FFFFFF; --sunk:#F7EFEB; --row:#FDFAF9;
  --line:#E6D8D2; --line2:#D3BFB7;
  --ink:#2E1512; --dim:#77574F; --faint:#8F7466;
  --accent:#3E1B15; --accent-ink:#FFFFFF; --accent-soft:#F4E6E1;
  --gold:#FDC147; --gold-deep:#8A5A0C; --brandred:#D6293A;
  /* the poster's red band, and what sits on it */
  --band:#D6293A; --band-deep:#AF2230; --band-ink:#FFFFFF;
  --berry:#8E3A63; --on-berry:#FFFFFF; --ok:#2F6B4F; --ok-soft:#E2F0E8;
  --warn:#8A5A0C; --warn-soft:#FBEFD5;
  /* The cells a person types on the payroll. Warm, so they read as live
     rather than disabled: a grey box says 'you cannot', and these are the
     only boxes on that screen where you can. */
  --typed:#FFF4DC; --typed-edge:#F2E0B4;
  --crit:#CA3747; --crit-soft:#FBE3E5;
  /* The tin the cake is baked in — shape. Blue because red, green and yellow
     are all spoken for on the production board and mean other things. */
  --tin:#2B5C86; --on-tin:#FFFFFF;
  /* A Yeyyadi order sitting on the Production Unit's board. */
  --yey-soft:#EFE9F7; --yey-line:#7E5AA6;
  --shadow:0 10px 40px -12px rgba(46,21,18,.28);
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --ground:#141010; --panel:#1E1817; --sunk:#191413; --row:#221B1A;
  --line:#332826; --line2:#4B3B36;
  --ink:#F3E9E5; --dim:#BCA49B; --faint:#93796F;
  --accent:#FDC147; --accent-ink:#2A1310; --accent-soft:#3A2A16;
  --gold:#FDC147; --gold-deep:#FDC147; --brandred:#F0736F;
  --band:#8E1B26; --band-deep:#6E141D; --band-ink:#FFF3F1;
  --berry:#E894BC; --on-berry:#2A1310; --ok:#63C08C; --ok-soft:#16291F;
  --warn:#E5913C; --warn-soft:#2E2113;
  --typed:#2C2114; --typed-edge:#4C3A1E;
  --crit:#F0736F; --crit-soft:#331A18;
  --tin:#8FBEE6; --on-tin:#12222E;
  --yey-soft:#251E36; --yey-line:#B79BE0;
  --shadow:0 10px 40px -12px rgba(0,0,0,.8);
}}
:root[data-theme="dark"]{
  --ground:#141010; --panel:#1E1817; --sunk:#191413; --row:#221B1A;
  --line:#332826; --line2:#4B3B36;
  --ink:#F3E9E5; --dim:#BCA49B; --faint:#93796F;
  --accent:#FDC147; --accent-ink:#2A1310; --accent-soft:#3A2A16;
  --gold:#FDC147; --gold-deep:#FDC147; --brandred:#F0736F;
  --band:#8E1B26; --band-deep:#6E141D; --band-ink:#FFF3F1;
  --berry:#E894BC; --on-berry:#2A1310; --ok:#63C08C; --ok-soft:#16291F;
  --warn:#E5913C; --warn-soft:#2E2113;
  --typed:#2C2114; --typed-edge:#4C3A1E;
  --crit:#F0736F; --crit-soft:#331A18;
  --tin:#8FBEE6; --on-tin:#12222E;
  --yey-soft:#251E36; --yey-line:#B79BE0;
  --shadow:0 10px 40px -12px rgba(0,0,0,.8);
}

*{box-sizing:border-box}
[hidden]{display:none !important}
body{margin:0;background:var(--ground);color:var(--ink);
  font-family:Inter,system-ui,-apple-system,"Segoe UI",sans-serif;font-size:13px;line-height:1.45;
  -webkit-font-smoothing:antialiased}
.mono{font-family:"IBM Plex Mono",ui-monospace,monospace}
.num{font-variant-numeric:tabular-nums}
h1,h2,h3{font-family:Fraunces,Georgia,serif;font-weight:700;letter-spacing:-.01em;margin:0}

/* ------------------------------------------------------------- chrome ---- */
/* Just enough room to breathe under the last box — 40px of it was pushing
   a busy order into a scroll on a 1600-wide counter screen. */
/* =============================================================== the shell ==
   THE SHOP ASKED FOR IT: "I want the header to be static and also no vertical
   scroll bar for the whole BCH360 (except within the pages)."

   So the window itself never scrolls. The shell is exactly the height of the
   viewport, the band is pinned at the top of it, and everything below is one
   region that scrolls on its own. A long screen still scrolls — it has to —
   but the band stays put and the browser's own bar down the side of the whole
   application is gone.
   ========================================================================== */
html,body{height:100%;overflow:hidden}
#root{height:100%;display:flex;flex-direction:column;min-height:0}
main.app{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;
  padding:0 12px 20px}
/* The band does not scroll away with the page any more. It is a flex item that
   simply refuses to shrink. */
header.bar{flex:0 0 auto}
/* The poster's red band. The pattern is the shop's own artwork, laid under a
   red wash so the bakery icons show through a shade darker — the same trick the
   poster uses, rather than a flat rectangle of colour. */
.bar{display:flex;align-items:center;gap:12px;padding:12px 14px;flex-wrap:wrap;
  border-bottom:3px solid var(--gold);border-radius:0 0 6px 6px;
  color:var(--band-ink);
  background-color:var(--band);
  background-image:url("assets/pattern.jpg");
  background-size:340px auto;background-position:center;
  /* multiply, not a wash: the artwork is pale icons on white, so white leaves
     the red alone and the icons come through a shade deeper — which is what the
     poster's band actually does. */
  background-blend-mode:multiply}

/* The brand is a link now, so it needs the link reset the nav pills get —
   otherwise the browser underlines "BCH360." and paints it link-blue. */
.brand{display:flex;align-items:center;gap:8px;text-decoration:none;color:inherit}
a.brand{cursor:pointer;border-radius:4px;padding:2px 4px;margin:-2px -4px;
  transition:background .12s}
a.brand:hover{background:rgba(255,255,255,.10)}
.card a.brand:hover{background:transparent}
.brand img{height:32px;width:auto;display:block}
.brand .btxt{display:flex;flex-direction:column;line-height:1}
.brand .bname{font-family:Fraunces,Georgia,serif;font-weight:700;font-size:19px}
.bar .brand .bname{color:var(--band-ink)}
.brand .bname i{font-style:normal;color:var(--brandred)}
/* On the red band the full stop has to be the gold, not the red it is sitting on. */
.bar .brand .bname i{color:var(--gold)}
.brand .bsub{font-family:"IBM Plex Mono",monospace;font-size:8px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--faint);margin-top:4px;white-space:nowrap}
.bar .brand .bsub{color:rgba(255,255,255,.72)}
@media(max-width:760px){.brand .bsub{display:none}}

.nav{display:flex;gap:2px;background:var(--sunk);border:1px solid var(--line);border-radius:4px;padding:2px}
.nav a{font:inherit;font-size:12px;color:var(--dim);padding:4px 10px;border-radius:4px;
  text-decoration:none;cursor:pointer}
.nav a:hover{color:var(--ink)}
.nav a.on{background:var(--panel);color:var(--ink);box-shadow:0 1px 2px rgba(0,0,0,.12);font-weight:600}
/* The nav in the band: white pill on red, exactly as the poster puts white type
   on its red. Everything else is the band's own ink. */
.bar .nav{background:rgba(0,0,0,.16);border-color:rgba(255,255,255,.22)}
.bar .nav a{color:rgba(255,255,255,.82)}
.bar .nav a:hover{color:#FFF}
.bar .nav a.on{background:#FFF;color:var(--band);box-shadow:0 1px 3px rgba(0,0,0,.28)}
.spacer{flex:1}
/* ---- today against its target, in the band ---------------------------- */
/* A single gold pill in the shop's own yellow, sitting on the red band the way
   the poster's gold sits on it. What it replaced was a two-tone bar that filled
   up across the middle of its own text — half gold, half dark, the money
   straddling the join — which read as a broken progress widget rather than as a
   figure. Here the number is the thing and the small track beside it is the
   glance. */
.tgt{display:flex;align-items:center;height:34px;padding:0 4px 0 14px;
  border-radius:999px;background:var(--gold);
  border:1px solid rgba(62,27,21,.18);
  box-shadow:0 1px 0 rgba(255,255,255,.45) inset, 0 2px 8px -4px rgba(0,0,0,.45);
  color:#3E1B15;white-space:nowrap}
.tgt:empty{display:none}
.tgt-face{display:flex;align-items:center;gap:8px}
.tgt-out{font-family:"IBM Plex Mono",monospace;font-size:8px;letter-spacing:.14em;
  text-transform:uppercase;opacity:.66}
.tgt-now{font-family:Fraunces,Georgia,serif;font-size:17px;line-height:1;
  font-variant-numeric:tabular-nums}
.tgt-of{font-style:normal;font-size:11px;opacity:.7}
/* The glance: how far along, in one small rounded track. */
.tgt-track{width:46px;height:6px;border-radius:999px;overflow:hidden;
  background:rgba(62,27,21,.2)}
.tgt-fill{display:block;height:100%;border-radius:999px;background:#3E1B15;
  transition:width .5s ease}
.tgt-pct{font-family:"IBM Plex Mono",monospace;font-size:10px;font-weight:700;
  font-variant-numeric:tabular-nums;
  background:rgba(62,27,21,.12);border-radius:999px;padding:4px 8px}
.tgt-party{font-size:14px;line-height:1}
/* Beaten: the track is full and the percentage stops being a quiet chip. */
.tgt.hit{background:#FFD97A}
.tgt.hit .tgt-pct{background:#3E1B15;color:var(--gold)}
@media(max-width:1180px){.tgt-track,.tgt-of{display:none}}
@media(max-width:980px){.tgt{padding-left:10px}.tgt-out{display:none}}

/* ---- beating it ------------------------------------------------------- */
.party{position:fixed;left:50%;top:82px;transform:translateX(-50%);z-index:60;
  display:flex;align-items:center;gap:12px;padding:14px 20px;border-radius:8px;
  background:var(--panel);border:1px solid var(--ok);box-shadow:var(--shadow);
  animation:party-in .45s cubic-bezier(.2,1.4,.4,1)}
.party.go{opacity:0;transition:opacity .9s ease}
.party-pop{font-size:26px;animation:party-pop 1.1s ease-in-out 2}
.party b{display:block;font-family:Fraunces,Georgia,serif;font-size:17px}
.party span{font-size:12px;color:var(--dim)}
@keyframes party-in{from{opacity:0;transform:translate(-50%,-14px) scale(.94)}
  to{opacity:1;transform:translate(-50%,0) scale(1)}}
@keyframes party-pop{0%,100%{transform:scale(1) rotate(0)}
  30%{transform:scale(1.25) rotate(-12deg)}65%{transform:scale(1.1) rotate(10deg)}}

.confetti{position:fixed;inset:0;z-index:59;pointer-events:none;overflow:hidden}
.confetti i{position:absolute;top:-16px;width:8px;height:13px;border-radius:4px;
  animation:confetti-fall 3.4s linear forwards}
@keyframes confetti-fall{
  0%{opacity:0;transform:translateY(0) rotate(0)}
  8%{opacity:1}
  100%{opacity:0;transform:translateY(102vh) rotate(760deg)}}
/* Nobody should be made dizzy by a sales figure. */
@media (prefers-reduced-motion:reduce){
  .confetti{display:none}
  .party,.party-pop{animation:none}
}
.who{text-align:right;line-height:1.2}
.who b{display:block;font-size:12px}
.who i{font-style:normal;font-size:9px;letter-spacing:.09em;text-transform:uppercase;color:var(--faint)}
.bar .who b{color:var(--band-ink)}
.bar .who i{color:var(--gold)}
.bar button.ghost{color:rgba(255,255,255,.88);border-color:rgba(255,255,255,.34)}
.bar button.ghost:hover{color:#FFF;background:rgba(255,255,255,.14);border-color:#FFF}

/* ------------------------------------------------------------ controls --- */
button,.btn{font:inherit;font-size:12px;font-weight:600;padding:6px 14px;border-radius:4px;
  border:1px solid var(--line2);background:var(--panel);color:var(--ink);cursor:pointer}
button:hover,.btn:hover{border-color:var(--accent)}
button.primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
button.primary:disabled{opacity:.45;cursor:not-allowed;border-color:var(--line2)}
button.ghost{background:transparent;border-color:transparent;color:var(--dim)}
button.ghost:hover{color:var(--ink)}
/* A checkbox must never be stretched by the width:100% below — that is what
   pushes its label halfway across the row. */
input[type=checkbox],input[type=radio]{width:auto;margin:0;accent-color:var(--accent);cursor:pointer}
.tickrow{display:flex;align-items:center;gap:20px;flex-wrap:wrap}
/* One line of narrow numeric fields — the whole of a cake's money in a glance. */
.cakerow{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap}
/* The collection rows: a few fixed-width controls, the rest sharing what is left. */
.colrow{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap}
.cakerow input,.cakerow select{padding:6px 6px}
.cakerow label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tickrow label{display:inline-flex;align-items:center;gap:6px;margin:0;
  text-transform:none;letter-spacing:0;font-family:inherit;font-size:12px;
  font-weight:500;color:var(--ink);cursor:pointer}
input,select,textarea{width:100%;font:inherit;font-size:13px;color:var(--ink);background:var(--panel);
  border:1px solid var(--line2);border-radius:4px;padding:6px 8px}
input:focus,select:focus,textarea:focus{outline:2px solid var(--accent);outline-offset:-1px;border-color:var(--accent)}

/* WHERE THE KEYBOARD IS. BCH360 is worked at speed with Ctrl+S and Ctrl+Enter,
   and until now only the boxes said where the focus had got to - a button, a
   nav tab or a chip took it silently, so tabbing through a screen was a guess.
   One rule for all of them, said once, so no screen can have its own idea of
   what focus looks like. :focus-visible and not :focus, because a mouse click
   on a button should not leave a ring behind it. */
button:focus-visible,.btn:focus-visible,a:focus-visible,summary:focus-visible,
[role="button"]:focus-visible,[tabindex]:focus-visible{
  outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
.bar button:focus-visible,.bar a:focus-visible{outline-color:var(--gold)}

/* Figures line up down a column, wherever they are. The classes below existed
   one at a time, screen by screen; this is the same rule said once for every
   cell that carries money or a count. */
td.r,th.r,.num,input.num,.money b,.tot b{font-variant-numeric:tabular-nums}
input::placeholder{color:var(--faint)}
label{display:block;font-size:10px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--faint);margin-bottom:3px;font-family:"IBM Plex Mono",monospace}
kbd{font-family:"IBM Plex Mono",monospace;font-size:10px;background:var(--sunk);border:1px solid var(--line);
  border-bottom-width:2px;border-radius:4px;padding:0px 4px;color:var(--dim)}

/* ------------------------------------------------------------- panels ---- */
.grid{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:14px;margin-top:14px;align-items:start}
/* DAY END, in three columns of equal width. See the note in dayend.js: the
   close was spreading itself across the whole of a shop monitor with every
   figure a hand's width from its own label. */
.grid.three{grid-template-columns:repeat(3,minmax(0,1fr));
  max-width:1240px;margin-left:auto;margin-right:auto}
.grid.three > div{display:flex;flex-direction:column;gap:14px;min-width:0}
/* The drawer takes two of the three, and splits them itself. */
.grid.three .drawercard{grid-column:span 2}
.grid.three > div:has(.drawercard){grid-column:span 2}
.drawerbody{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:16px;align-items:start}
.drawerbody > .hint{grid-column:2;align-self:end;padding-top:0}
@media (max-width:1200px){
  .grid.three{grid-template-columns:minmax(0,1fr)}
  .grid.three > div:has(.drawercard){grid-column:auto}
  .drawerbody{grid-template-columns:minmax(0,1fr)}
  .drawerbody > .hint{grid-column:auto}
}
/* The figure belongs to the words beside it, not to the far edge of the room. */
.grid.three .tl b{margin-left:auto;max-width:none}
.grid.three .panel{max-width:520px}
.grid.three .drawercard{max-width:none}
/* The office close: two columns, capped and centred like the counter's. */
.grid.two{grid-template-columns:repeat(2,minmax(0,1fr));
  max-width:1040px;margin-left:auto;margin-right:auto}
.grid.two > div{display:flex;flex-direction:column;gap:14px;min-width:0}
@media(max-width:980px){.grid{grid-template-columns:1fr}}
/* Both columns end on the same line: the shorter one stretches, and whatever it
   marks .fill is pushed to the foot of it. */
.grid.level{align-items:stretch}
.grid.level>*{display:flex;flex-direction:column;min-width:0}
.grid.level .fill{margin-top:auto}
/* Who and where · how they paid · what it comes to. Three narrow columns beat
   two wide ones here: the page stops scrolling and no box is wider than the
   longest thing in it. */
.grid3{display:grid;
  grid-template-columns:minmax(0,1.35fr) minmax(0,1fr) minmax(0,1fr);
  gap:14px;align-items:stretch}
.grid3>*{display:flex;flex-direction:column;min-width:0}
.grid3 .fill{margin-top:auto}
@media(max-width:1280px){.grid3{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
@media(max-width:860px){.grid3{grid-template-columns:1fr}}
/* A row you can open. */
tbody tr.clickable{cursor:pointer}
tbody tr.clickable:hover td{background:var(--accent-soft)}
/* The banner that says which bill is open for correction. */
.note-edit{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  padding:8px 10px;border-radius:4px;font-size:12px;
  background:var(--warn-soft);border:1px solid var(--warn);color:var(--warn)}
.note-edit b{color:var(--ink)}
/* Four boxes across: decoration · customer and delivery · money · payment.
   Money and payment are the narrowest of the four — a label and a figure need
   far less room than a name, an address and a phone number do. */
.grid4{display:grid;
  grid-template-columns:minmax(0,1.05fr) minmax(0,1.4fr) minmax(0,.85fr) minmax(0,.9fr);
  gap:14px;align-items:stretch}
.grid4>*{display:flex;flex-direction:column;min-width:0}
.grid4 .fill{margin-top:auto}
@media(max-width:1300px){.grid4{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
@media(max-width:900px){.grid4{grid-template-columns:1fr}}
/* One payment mode per line — a row of them wrapped badly and read as a jumble. */
.paycol{display:flex;flex-direction:column;gap:6px}
.paycol button{width:100%;text-align:left}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:4px;margin-top:12px}
.phead{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--line);
  background:var(--sunk);border-radius:4px 4px 0 0}
.phead h2{font-size:10px;font-weight:600;letter-spacing:.13em;text-transform:uppercase;
  color:var(--faint);font-family:"IBM Plex Mono",monospace}
.phead .r{margin-left:auto;font-size:11px;color:var(--faint)}
.pbody{padding:12px}
.row{display:grid;gap:8px}
.r2{grid-template-columns:1fr 1fr}
.r3{grid-template-columns:1fr 1fr 1fr}
.stack{display:flex;flex-direction:column;gap:10px}
.hint{font-size:11px;color:var(--faint);padding:8px 2px 0}

/* ------------------------------------------------- the wide cake row ----- */
/* Everything true about one cake belongs on one line. On a narrow screen that
   line is wider than the screen, so it scrolls sideways inside its own box —
   the page itself never does. */
.xscroll{overflow-x:auto;overflow-y:visible;margin:0 -12px;padding:0 12px}
/* Fixed layout, so every column is the width it was given rather than the width
   the longest value happens to want — otherwise one long message squeezes the
   quantity down to nothing. The one column with no width set, Additional info,
   takes whatever room is left over on a wide screen. */
.cakes{table-layout:fixed;width:100%;min-width:1626px}
.cakes thead th{padding:6px 4px;overflow:hidden;text-overflow:ellipsis}
.cakes tbody td{padding:4px;height:auto;vertical-align:middle}
.cakes tbody tr:nth-child(even) td{background:transparent}
.cakes tbody tr:hover td{background:transparent}
.cakes input,.cakes select{padding:4px 6px;font-size:12px}
/* The spinner arrows are useless on a counter and steal a third of a narrow
   column — enough to hide the digit that is in it. */
/* Date, Time and Cake stay put while the rest of the row scrolls, so you can
   never be typing a message into a line without knowing which cake it is.
   The offsets are measured from the real header cells after layout, not
   hardcoded — a wide screen hands the spare width to the columns and a guessed
   offset would park the Cake cell on top of the Size one. */
.cakes th:nth-child(1),.cakes td:nth-child(1){position:sticky;left:0}
.cakes th:nth-child(2),.cakes td:nth-child(2){position:sticky;left:var(--c2,126px)}
.cakes th:nth-child(3),.cakes td:nth-child(3){position:sticky;left:var(--c3,214px);
  box-shadow:1px 0 0 var(--line2)}
/* A sticky cell must be opaque or the columns sliding beneath it show through.
   The extra :nth-child(n) is only there to out-specify the zebra striping. */
.cakes tbody tr:nth-child(n) td:nth-child(-n+3),
.cakes tbody tr:hover td:nth-child(-n+3){background:var(--panel);z-index:2}
.cakes th:nth-child(-n+3){z-index:4}
.cakes input[type=number]{-moz-appearance:textfield}
.cakes input[type=number]::-webkit-outer-spin-button,
.cakes input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.cakes td.tc,.cakes th.tc{text-align:center}
/* ===========================================================================
   THE LAYER LADDER. Written down because this shop has now met the same fault
   three times: something opens, is drawn correctly, and is invisible because a
   panel is sitting on top of it. Twice it looked like a dead button.

      60   .party, .confetti     a celebration, never over a decision
     400   .sheet-back           a bill or a receipt opened over a screen
     500   .rowmenu, .addmenu    a menu raised from the band or a row
     520   .picker, .take,       a LIST ATTACHED TO A CONTROL. Above the sheet,
           .headmenu             because the control it belongs to is often
                                 inside one — the decoration box on a bill is
                                 exactly that, and at 200 its list opened behind
                                 the panel and the shop reported it could not
                                 add a decoration while editing an order.
     600   .askback              a question that stops everything
     700   .hovernote
     800   #toast                A MESSAGE. Never behind anything, ever.

   Anything new that floats goes on this ladder, and test/run.mjs fails if a
   list-attached-to-a-control ever sinks below the sheet again.
   =========================================================================== */

/* The cake is chosen in the row itself. Its list of matches is fixed-positioned
   off the body, because anything inside .xscroll is clipped by it. */
.picker{position:fixed;z-index:520;max-height:290px;overflow:auto;
  background:var(--panel);border:1px solid var(--line2);border-radius:4px;
  box-shadow:var(--shadow);padding:0 0 3px}
.picker .grp{position:sticky;top:0;background:var(--sunk);color:var(--faint);
  font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.13em;
  text-transform:uppercase;font-weight:600;padding:6px 10px 4px;
  border-bottom:1px solid var(--line)}
.picker .opt{display:grid;grid-template-columns:56px minmax(0,1fr) auto;gap:8px;
  align-items:center;padding:6px 10px;cursor:pointer;border-bottom:1px solid var(--line)}
.picker .opt b{color:var(--accent);font-size:11px}
.picker .opt .sub{color:var(--faint);font-size:11px;margin-left:7px}
.picker .opt:hover,.picker .opt.on{background:var(--accent-soft)}
/* A label sitting inline in a panel heading, next to its control. */
.hlbl{font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.13em;
  text-transform:uppercase;font-weight:600;color:var(--faint)}
/* Ready cake / Order cake, per line — a cake for next Saturday cannot be one
   that is on the shelf now, so the row says which it is. */
.chip{display:inline-block;flex:0 0 auto;font-family:"IBM Plex Mono",monospace;
  font-size:8px;letter-spacing:.08em;text-transform:uppercase;font-weight:600;
  padding:2px 6px;border-radius:4px;border:1px solid var(--line2);
  color:var(--faint);text-decoration:none;cursor:pointer;white-space:nowrap}
.chip:hover{border-color:var(--accent);color:var(--ink)}
.chip.chip-on{background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}
/* A cake being MADE for this order, as against one lifted off the display. The
   same dark the day board uses for the same fact. */
/* On the order form the chip sits beside the cake box and is a control in its
   own right, so it stands the same height and is read at the same distance. */
.chip.chip-lg{display:inline-flex;align-items:center;font-size:11px;
  padding:0 12px;border-radius:4px;letter-spacing:.06em}
.chip.chip-order{background:var(--ink);border-color:var(--ink);color:var(--panel)}
.chip.chip-order:hover{border-color:var(--accent);color:var(--panel)}
/* A cheesecake is always made to order — it is set in a springform tin and none
   of them ever stands on the display. Not a decision, so it does not look like
   a button waiting to be pressed. */
/* WHETHER THE CAKE IS DRIVEN ACROSS TOWN OR HANDED OVER AT THE WINDOW is one of
   the larger decisions on the order screen, and it was a 13px label beside a
   13px tick, tucked against the Collect at box like an afterthought. */
/* THE SAME HEIGHT AS THE BOX BESIDE IT, as the shop asked. It stood 42px
   against a 31px select and read as a different kind of thing on a row where
   both are answers to the same question. It keeps the weight and the colour it
   earns when it is ticked; it stops standing a head taller. */
.bigtick{display:flex;align-items:center;gap:8px;margin:0;cursor:pointer;
  font-size:13px;font-weight:600;color:var(--ink);line-height:17px;
  padding:6px 10px;border:1px solid var(--line2);border-radius:6px;
  background:var(--sunk);white-space:nowrap;align-self:flex-end}
.bigtick:hover{border-color:var(--accent)}
.bigtick input[type=checkbox]{width:16px;height:16px;margin:0;flex:0 0 auto;
  accent-color:var(--accent);cursor:pointer}
.bigtick:has(input:checked){border-color:var(--accent);background:var(--accent-soft);
  color:var(--accent)}

.chip.chip-fixed{cursor:default;opacity:.72}
.chip.chip-fixed:hover{border-color:var(--ink)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .chip.chip-on{color:var(--gold)}}
:root[data-theme="dark"] .chip.chip-on{color:var(--gold)}

/* -------------------------------------------------------------- table ---- */
.scroll{overflow:auto;max-height:calc(100vh - 250px)}
table{border-collapse:separate;border-spacing:0;width:100%;font-size:12px}
thead th{position:sticky;top:0;z-index:3;background:var(--sunk);font-family:"IBM Plex Mono",monospace;
  font-size:9px;font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--faint);
  text-align:left;padding:6px 8px;border-bottom:1px solid var(--line2);white-space:nowrap}
tbody td{padding:0 8px;height:32px;border-bottom:1px solid var(--line);white-space:nowrap;vertical-align:middle}
tbody tr:nth-child(even) td{background:var(--row)}
tbody tr:hover td{background:var(--accent-soft)}
.tr{text-align:right}
td.cake{white-space:normal;min-width:180px}
td.cake b{color:var(--accent);font-family:"IBM Plex Mono",monospace;font-size:11px}
tfoot td{position:sticky;bottom:0;z-index:3;background:var(--sunk);border-top:2px solid var(--line2);
  font-weight:600;padding:8px;font-variant-numeric:tabular-nums;white-space:nowrap}
.empty{padding:32px 12px;text-align:center;color:var(--faint)}
.empty b{display:block;font-family:Fraunces,Georgia,serif;font-size:19px;color:var(--ink);margin-bottom:4px}

.pill{font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.05em;text-transform:uppercase;
  padding:2px 4px;border-radius:4px;border:1px solid currentColor}
.pill.ok{color:var(--ok)} .pill.wait{color:var(--warn)} .pill.due{color:var(--crit)}
.pill.cash{color:var(--berry)} .pill.bank{color:var(--accent)} .pill.ctr{color:var(--faint)}
/* Balances: which way the money is owed. .due was taken, so these are named
   for the colour they carry rather than the direction. */
.pill.crit{color:var(--crit)} .pill.warn{color:var(--warn)} .pill.dim{color:var(--faint)}

/* --------------------------------------------------------------- signin -- */
/* The poster in one screen: the red ground with the pattern in it, a white card
   on top, a gold rule under the name. */
.signin{min-height:100vh;display:grid;place-items:center;padding:20px;
  background-color:var(--band);
  background-image:url("assets/pattern.jpg");
  background-size:420px auto;background-blend-mode:multiply}
.card{width:360px;max-width:100%;background:var(--panel);border:1px solid var(--line);
  border-top:5px solid var(--gold);
  border-radius:8px;box-shadow:0 26px 60px -18px rgba(0,0,0,.45);padding:24px 24px 20px}
.card .brand{justify-content:center;margin-bottom:18px}
.card .brand img{height:52px}
.card .brand .bname{font-size:26px}

/* --------------------------------------------------------------- toast --- */
/* A MESSAGE NOBODY CAN READ is worse than no message: it leaves the counter
   watching BCH360 refuse something and saying nothing about why. There is no
   longer a bar across the bottom to hide behind, but the z-index stays high on
   purpose — this corner is the one thing on the screen that must never end up
   under anything else. */
#toast{position:fixed;right:16px;bottom:16px;z-index:800;display:flex;flex-direction:column;gap:8px}
.toast{background:var(--panel);border:1px solid var(--line2);border-left:4px solid var(--crit);
  border-radius:4px;padding:8px 14px;box-shadow:var(--shadow);max-width:380px;font-size:12px;
  transition:opacity .3s, transform .3s}
.toast.good{border-left-color:var(--ok)}
.toast.out{opacity:0;transform:translateY(6px)}

.loading{padding:40px;text-align:center;color:var(--faint)}

/* =========================================================== the thermal bill ==
   80mm paper. THE PRINTABLE STRIP IS 68mm, which is not a guess: it is what
   Vyapar is set to, and Vyapar's bills come off this printer whole.
//
   EVERY SIZE HERE IS PHYSICAL — pt and mm, never px. A px is a screen unit, and
   a screen at 125% or 150% Windows scaling redefines it. That is what put a
   third of the bill off the edge of the paper on 30 August: the layout was
   right, the characters simply arrived about half again the size they were
   drawn at. A point is 1/72 of an inch on any display, at any scaling.

   7pt monospace advances 0.6em, so a character measures 1.481mm and 45 of them
   fit the 68mm strip — measured, not assumed: 46 comes to 68.1mm and the last
   one would be shaved. The shop's own bill fits about 46, so this is the same
   line the counter is used to reading.
   Everything is text: no image to smudge, nothing that depends on the printer's
   own graphics mode.
   ============================================================================ */
.bill{width:68mm;margin:0 auto;padding:2mm 0 0;
  font-family:"IBM Plex Mono",ui-monospace,"Courier New",monospace;
  font-size:7pt;line-height:1.42;color:#000;background:#fff;
  -webkit-font-smoothing:none}
.bill .b-name{text-align:center;font-size:10pt;font-weight:700;letter-spacing:.02em}
.bill .b-mid{text-align:center}
.bill .b-title{text-align:center;font-weight:700;letter-spacing:.22em}
.bill .b-rule{border-top:.3mm dashed #000;margin:1mm 0;height:0}
.bill .b-rule.hard{border-top-style:solid;border-top-width:.6mm}
.bill .b-pair{display:flex;justify-content:space-between;gap:1.5mm}
.bill .b-pair span:last-child{white-space:nowrap}
.bill .b-bold{font-weight:700;font-size:8.5pt}
.bill .b-item{font-weight:700;word-break:break-word}
.bill .b-note{font-style:italic;padding-left:5mm}
.bill .b-sub{padding-left:5mm}
/* Thermal cutters take the paper a few millimetres above the head. */
.bill .b-feed{height:14mm}

/* On screen it is a preview: a paper-coloured slip on the page ground. */
.bill-preview{background:#fff;color:#000;border:1px solid var(--line2);
  border-radius:4px;box-shadow:var(--shadow);padding:4mm 3mm;width:78mm}

@media print{
  /* The PAPER is 80mm, so that is the page — asking for 68mm invites the driver
     to scale a narrow page up to fill the roll, which is the same fault again
     wearing a different hat. The bill sits 68mm wide in the middle of it. */
  @page{size:80mm auto;margin:0}
  html.printing body>*{display:none !important}
  html.printing body>#printarea{display:block !important}
  #printarea{position:static;width:80mm}
  .bill{width:68mm;font-size:7pt}
}


/* ------------------------------------------------------- the day board ---- */
/* Fixed columns: the cake name is the one that wants to run away with the width,
   and every figure column has to stay under its heading. */
/* The three columns that carry words share whatever is left over; every other
   column keeps exactly the width it was given. See the note on COLS in
   dayboard.js — a figure column that grows on a wide monitor is width spent on
   a dash. */
.board{table-layout:fixed;width:100%;min-width:1340px}
.board col.flexcol{width:auto}
/* A column of right-aligned figures needs less air than a column of words: the
   eye reads down the last digit, not across the cell. */
.board td.tr,.board th.tr{padding-left:4px;padding-right:8px}
/* And its HEADING is what sets its width — nine point mono in capitals with a
   tenth of an em between the letters is wider than the four digits under it.
   Tightening the tracking on the figure headings alone buys back the width of
   two whole columns and costs nothing anybody reads. */
.board thead th.tr{letter-spacing:.04em}
.board thead th{overflow:hidden;text-overflow:ellipsis}
/* ONE LINE PER CAKE. Wrapping made a column of ragged two- and three-line rows
   that had to be read rather than scanned, and a board is scanned — the eye
   goes down the codes. A long name gives way at its end, where the least is
   lost: the code and the size are what identify the cake, and the pills are
   what change what happens next. Hovering, and the bill behind the row, still
   carry the whole name. */
.board td.cake{white-space:nowrap;min-width:0;line-height:1.3;
  display:flex;align-items:center;overflow:hidden}
/* The NAME is what gives way, not the cell. Truncating the cell as a whole cut
   the last pill in half and left a coloured stub that looked like a rendering
   fault — and lost the one thing on the row that says what happens next. */
.board td.cake .cname{flex:0 1 auto;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.board td.cake .pill{flex:0 0 auto;padding:0px 4px;font-size:8px;
  margin-left:5px !important}
.board td.wrap{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  color:var(--dim);font-size:12px}
/* THE THINGS A COUNTER READS OUT LOUD — the time, the message, the instruction
   somebody typed, the number they are about to ring. They were 12px and grey on
   a 13px board, which made the four facts most likely to be spoken aloud the
   four quietest things on the row. They now carry the weight of the Line total,
   which is what was asked for and is right: this is the row, not its footnotes.
   .said after .wrap so it wins on colour and size. */
.board td.said{color:var(--ink);font-size:12px;font-weight:600}
/* WHERE IT IS BAKED. Blue, because it is a place and not a state — the pills
   either side of it say what has happened to the cake. */
.pill.prod{background:var(--tin);color:var(--on-tin)}
/* A pill you press: the counter's handover tick. */
.pill.tick{text-decoration:none;cursor:pointer;display:inline-block}
.pill.tick:hover{background:var(--accent-soft)}

/* ============================================================== day end ====
   Counting up. Two shapes: the running tally and the note grid. */

/* The tally reads as a sum on paper — labels left, figures in a column that
   lines up, and one ruled total. */
.tally{display:flex;flex-direction:column;gap:2px}
.tl{display:flex;align-items:baseline;gap:10px;padding:3px 0;font-size:12px}
.tl span{color:var(--dim)}
.tl span i{font-style:normal;color:var(--faint);font-size:11px;margin-left:6px}
.tl b{margin-left:auto;font-weight:500;white-space:nowrap}
.tl.sum{border-top:1px solid var(--line);margin-top:5px;padding-top:6px}
.tl.sum span{color:var(--ink)}
.tl.sum b{font-weight:700}

/* The verdict line. Green when it tallies, red when it does not — and "over"
   is not reassuring, so it is coloured too. */
.gap{margin-top:10px;border-top:1px solid var(--line);padding-top:8px}
.gap .tl.ok b{color:var(--ok)}
.gap .tl.over b,.gap .tl.short b{color:var(--crit)}
.gap .tl.over span,.gap .tl.short span{color:var(--crit);font-weight:600}

/* The count sheet. One column, ₹500 down to ₹1, the way a drawer is actually
   counted — you work down the notes in order, not across a grid. Each row shows
   what that bundle comes to, so a miscount shows itself while it is being typed. */
.notes{display:flex;flex-direction:column;gap:2px;padding:3px 0 0px}
.notes label{display:flex;align-items:center;gap:10px;margin:0}
.notes label .mono{width:40px;flex:0 0 40px;color:var(--dim);font-size:11px;text-align:right}
.notes label .x{color:var(--faint);font-size:10px}

/* At close the sheet carries two columns: what was counted this morning, and
   what is being counted now. The morning figure is a fact, not a field — it is
   set in the same tabular figures so the two line up down the page. */
.notes.two label{gap:0}
.notes.two label .mono{flex:0 0 42px}
.notes.two .was{flex:0 0 62px;text-align:right;padding-right:14px;
  font-variant-numeric:tabular-nums;font-size:12px;color:var(--dim)}
.notes.two .was.nil{color:var(--faint)}
.notes.two label input{margin-left:0}
.nhead{display:flex;align-items:baseline;gap:0;padding:0 0 3px;
  font-family:"IBM Plex Mono",monospace;font-size:8px;letter-spacing:.11em;
  text-transform:uppercase;color:var(--faint)}
.nhead span:nth-child(1){flex:0 0 42px}
.nhead span:nth-child(2){flex:0 0 62px;text-align:right;padding-right:14px}
.nhead span:nth-child(3){flex:0 0 74px;text-align:right;padding-right:6px}
.notes.two .nsum .was{flex:0 0 62px;padding-right:14px;font-weight:400}
.notes.two .nsum b:not(.was){flex:0 0 74px;text-align:right;margin-left:0;padding-right:6px}
.notes label input{width:74px;flex:0 0 74px;padding:4px 6px;font-size:12px;text-align:right}
.notes label i{font-style:normal;font-size:11px;color:var(--faint);
  margin-left:auto;white-space:nowrap;font-variant-numeric:tabular-nums}
/* The running total of the sheet, ruled off like the tally above it. */
.notes .nsum{display:flex;align-items:baseline;gap:10px;
  border-top:1px solid var(--line);margin-top:5px;padding-top:6px;font-size:12px}
.notes .nsum b{margin-left:auto;font-weight:700}

/* A quiet list inside a panel: the accounts that are not yours to tally. */
.lines{width:100%;border-collapse:collapse;margin-top:8px}
.lines td{padding:4px 4px;border-bottom:1px solid var(--line);font-size:12px;
  vertical-align:middle}
.lines tr:last-child td{border-bottom:0}
.lines .sub{color:var(--faint);font-size:11px;margin-left:7px}

/* A term of the sum you type rather than count: cash sent to the office. */
.tl .minus{color:var(--faint);margin-right:5px}
.tl b input{text-align:right}

/* Something is missing that everything below depends on. Not an error — the
   screen still works — but it must not read as a number. */
.warnline{background:var(--warn-soft);color:var(--warn);border:1px solid var(--line);
  border-radius:4px;padding:8px 10px;font-size:11px;line-height:1.45;margin-bottom:10px}

/* ============================================================== reports ====
   A register: many rows, one total at the foot that has to be right. Narrower
   and quieter than the day board — nothing here is being acted on, it is being
   read down a column. */
.board.report{min-width:860px}
.board.report tbody td{font-size:12px}
.board.report tfoot td{border-top:2px solid var(--line2);font-size:12px;
  background:var(--sunk)}
.board.report .sub{color:var(--faint);font-size:11px;margin-left:7px}
/* A row that opens its bill. The day board earns its pointer the same way. */
/* Dark carries the states the day board is really about: a cake being MADE for
   the order, a cake that IS baked, a cake handed over. Green was doing the same
   job as the amber next to it and reading as decoration rather than as a state. */
.pill.made{background:var(--ink);color:var(--panel);border-color:var(--ink)}
.pill.tick.made:hover{background:var(--accent);border-color:var(--accent)}
/* The Time heading is a control, not a label: the board is in the order the
   orders were taken, and sometimes the question is what is due this morning. */
.board th.timehead{cursor:pointer;user-select:none}
.board th.timehead:hover{color:var(--ink)}
.board th.timehead.on{color:var(--accent)}
.board th.timehead i{font-style:normal;font-size:9px}
.board tr.go{cursor:pointer}
.board tr.go:hover td{background:var(--accent-soft)}

/* ======================================================= taking a balance ====
   A small panel hanging off the Due figure on the day board. Deliberately not a
   dialog: the row it belongs to stays visible behind it, because the thing you
   are about to do is to THAT bill. */
.due-take{font-variant-numeric:tabular-nums;color:var(--crit);font-weight:600;
  text-decoration:none;border-bottom:1px dashed var(--crit);cursor:pointer}
.due-take:hover{background:var(--accent-soft);border-bottom-style:solid}
.take{position:fixed;z-index:520;width:326px;background:var(--panel);
  border:1px solid var(--line2);border-radius:4px;
  box-shadow:0 10px 30px rgba(0,0,0,.24)}
.take-head{display:flex;align-items:baseline;gap:8px;padding:8px 12px;
  border-bottom:1px solid var(--line);background:var(--sunk);
  border-radius:4px 4px 0 0;font-size:12px}
.take-head b{font-family:"IBM Plex Mono",monospace;font-size:12px}
.take-head .r{margin-left:auto;color:var(--crit);font-weight:600;white-space:nowrap}
.take-body{padding:10px 12px;display:flex;flex-direction:column;gap:8px}
.take-body label{display:flex;align-items:center;gap:10px;margin:0;font-size:12px;
  color:var(--dim)}
.take-body label>span:first-child{flex:0 0 52px;color:var(--faint);
  font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.12em;
  text-transform:uppercase}
.take-body input{flex:1;text-align:right;padding:4px 8px}
.take-body select{flex:1;min-width:0;padding:4px 6px;font-size:12px}
/* WHERE THE MONEY GOES, in one press. This was a drop-down grouped under Cash /
   Card machine / Bank / Online: four headings, and two clicks to say one thing.
   Every account is now a button, and a press adds a line — the same gesture the
   order screen uses to take money, so it is one habit and not two. */
/* The mode is picked ON the line now — see the note in dayboard.js. Six
   accounts was six buttons before a rupee had been typed. */
.takelbl{display:block;font-family:"IBM Plex Mono",monospace;font-size:9px;
  letter-spacing:.12em;text-transform:uppercase;color:var(--faint);margin-bottom:5px}
/* Five hundred in cash and the rest on the machine: one line each. */
.take-lines{display:flex;flex-direction:column;gap:4px}
.take-lines:empty{display:none}
.take-line{display:grid;grid-template-columns:1fr 92px 24px;gap:6px;
  align-items:center}
.take-line select{min-width:0;padding:4px 6px;font-size:12px}
.take-line .take-acc{flex:1 1 auto;min-width:0;font-size:12px;color:var(--dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.take-line input{text-align:right;padding:4px 8px;min-width:0}
.take-line .x{padding:3px 6px;font-size:13px;line-height:1;color:var(--faint);
  text-align:center}
.take-line .x:hover{color:var(--crit)}
.take-body input[type=date]{flex:1;min-width:0;text-align:left;padding:4px 6px}
.take-body .sub{font-size:11px;color:var(--faint);min-height:16px}
.take-foot{display:flex;align-items:center;gap:8px;padding:8px 12px;
  border-top:1px solid var(--line);background:var(--sunk);border-radius:0 0 4px 4px}
/* A column you can sort by. Only the number columns — sorting by name is a
   question nobody asks of a sales report. */
.board.report th.sortable{cursor:pointer;user-select:none}
.board.report th.sortable:hover{color:var(--ink)}

/* ================================================== filtering a register ====
   Every heading sorts and filters. The metaphor is the spreadsheet they came
   from: click the heading, get sort at the top and a filter under it. */
.board.report th.headcell{cursor:pointer;user-select:none}
.board.report th.headcell:hover{color:var(--ink)}
.board.report th.headcell i{font-style:normal;font-size:9px}
.board.report th.filtered{color:var(--accent)}
.board.report th.filtered .dot{color:var(--accent)}

.headmenu{position:fixed;z-index:520;width:236px;background:var(--panel);
  border:1px solid var(--line2);border-radius:4px;overflow:hidden;
  box-shadow:0 10px 30px rgba(0,0,0,.24);font-size:12px}
.hm-sort{display:flex;flex-direction:column;border-bottom:1px solid var(--line)}
.hm-sort a{padding:6px 12px;color:var(--dim);text-decoration:none}
.hm-sort a:hover{background:var(--accent-soft);color:var(--ink)}
.hm-sort a.on{color:var(--accent);font-weight:600}
.hm-head{display:flex;align-items:baseline;gap:8px;padding:6px 12px 4px;
  font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint)}
.hm-head a{color:var(--accent);text-decoration:none;letter-spacing:0;
  font-family:inherit;font-size:9px}
.hm-head .r{margin-left:auto}
.hm-list{max-height:210px;overflow:auto;padding:0 6px 8px}
.hm-list label{display:flex;align-items:center;gap:8px;margin:0;padding:4px 6px;
  border-radius:4px;cursor:pointer}
.hm-list label:hover{background:var(--sunk)}
.hm-list label span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;color:var(--ink)}
.hm-list label i{font-style:normal;color:var(--faint);font-size:11px;
  font-variant-numeric:tabular-nums}
.hm-text{padding:8px 10px}
.hm-text input{width:100%}
.hm-nums{padding:8px 10px;display:flex;flex-direction:column;gap:6px}
.hm-nums label{display:flex;align-items:center;gap:8px;margin:0;color:var(--dim)}
.hm-nums label span{flex:0 0 62px;font-size:11px}
.hm-nums input{flex:1;min-width:0;text-align:right;padding:4px 6px}

/* What the filter is hiding, said out loud under the table. */
.filterbar{display:flex;align-items:center;gap:10px;padding:6px 2px 0;
  font-size:11px;color:var(--faint)}
.filterbar a{color:var(--accent);text-decoration:none}
.filterbar a:hover{text-decoration:underline}

/* ================================================================= shelf ====
   Counting the display down at night. Narrow, because it is read one line at a
   time with a cake in your other hand. */
.board.shelf{min-width:400px}
.board.shelf tbody td{vertical-align:top}
/* Code, cake and size on ONE line, in the order the counter says it out loud.
   Stacked, the size sat under the name — where the eye had to go looking for
   the one thing that tells two otherwise identical rows apart. */
.board.shelf .shelf-code{font-family:"IBM Plex Mono",monospace;font-size:11px;
  color:var(--accent)}
.board.shelf .shelf-item{font-size:12px}
.board.shelf .shelf-size{font-family:"IBM Plex Mono",monospace;font-size:11px;
  background:var(--accent-soft);color:var(--accent);border:1px solid var(--line2);
  border-radius:4px;padding:0px 4px;white-space:nowrap}
/* The counts are the point of the screen; they were the smallest thing on it. */
.board.shelf input{width:100%;text-align:right;padding:4px 6px;font-size:14px;
  font-weight:600;font-variant-numeric:tabular-nums;
  /* Chrome reserves room for the spinner even when it is hidden, which is what
     was clipping a two-digit count down to a bracket. */
  -moz-appearance:textfield}
.board.shelf input::-webkit-outer-spin-button,
.board.shelf input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.board.shelf tbody td{vertical-align:middle}
.board.shelf tbody td{padding:4px 6px}
.board.shelf .sub{color:var(--faint);font-size:11px;margin-left:7px}
/* A cake that was due before today and still has not come. */
/* ------------------------------------------------------------- the shelf --
   Three jobs, three equal columns, side by side. Each table was cut down to
   fit a third of the screen: without its own min-width a .board insists on
   1540px and the last column — the tick, the difference — falls off the edge
   where nobody will ever drag to find it. */
/* Not three equal thirds. The closing box carries five figure columns beside
   the cake where the other two carry one or two, so an equal split starves the
   column doing the most work — that is how "COUNTED" came to be printed as
   "COUNT…". It gets the extra width; the two lists beside it lose a little and
   notice it far less. */
.shelfcols{display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1.35fr);
  gap:12px;align-items:start}

.shelfcols>.panel{margin-top:12px;min-width:0}
/* Below this there is no room for three of anything; they stack instead. */
@media (max-width:1180px){ .shelfcols{grid-template-columns:1fr} }
/* In a narrow panel margin-left:auto throws the count to the far corner, away
   from the heading it belongs to. Keep it beside its own title. */
.shelfcols .phead{flex-wrap:wrap;row-gap:2px}
.shelfcols .phead .r{margin-left:0;color:var(--dim)}
.shelfcols .phead .r::before{content:'·';margin:0 7px 0 1px;color:var(--line2)}
.board.arrivals{min-width:330px}
.board.arrivals tbody td{padding:4px 6px;vertical-align:top}
.board.arrivals .sub{color:var(--faint);font-size:11px;margin-left:7px}
/* Bill, customer and the unit's word on it — read once, per row, never scanned
   as a column, so they sit under the cake rather than beside it. */
.board.arrivals .sub2{color:var(--faint);font-size:11px;margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.board.arrivals tr.late td{background:var(--warn-soft)}
/* ---- the day report --------------------------------------------------- */
/* One table: the date pinned at the left, then three sections beside it, so a
   day is a row you read straight across instead of the same date found three
   times in three places. */
.board.dayreport{min-width:1040px;table-layout:auto}
.board.dayreport td,.board.dayreport th{padding:4px 8px;font-size:12px;
  white-space:nowrap}
.board.dayreport th{padding:6px 8px}
/* The section headings sit above their own columns and are the only thing on
   the page allowed to be bigger than the column names under them. */
.board.dayreport tr.grouprow th{font-size:10px;color:var(--accent);
  border-bottom:1px solid var(--line);letter-spacing:.14em;text-align:center;
  height:26px}
.board.dayreport tr.grouprow th.dt{text-align:left}
/* Two header rows both pinned to top:0 land on top of each other and the
   section names vanish. The second one has to stack UNDER the first. */
.board.dayreport thead tr.grouprow th{top:0}
.board.dayreport thead tr:nth-child(2) th{top:26px}
/* A hairline where one section ends and the next begins — three sections need
   to be three sections at a glance, not twelve columns in a row. */
.board.dayreport .grp{border-left:2px solid var(--line2)}
/* Pinned: the date stays put however far right you scroll. */
.board.dayreport .dt{position:sticky;left:0;z-index:2;background:var(--panel);
  text-align:left;box-shadow:1px 0 0 var(--line)}
.board.dayreport thead .dt{background:var(--sunk);z-index:3;vertical-align:bottom}
.board.dayreport tfoot .dt{background:var(--sunk);font-weight:600}
.board.dayreport tbody tr:nth-child(even) .dt{background:var(--row)}
.board.dayreport tr.shut .dt{background:var(--sunk)}
/* Cash transfer is the same table with three columns instead of thirteen, so it
   does not need the day report's width to hold itself open. */
.board.dayreport.transfer{min-width:0}
/* A day nothing came up on: present, and visibly not a transfer. */
.board.dayreport.transfer tr.quiet td{color:var(--faint);background:var(--sunk)}
.board.dayreport.transfer tr.quiet .dt{background:var(--sunk)}
/* What the office counted, typed straight into the row it belongs to. */
.board.dayreport.transfer input.gotbox{width:100%;min-width:86px;text-align:right;
  padding:3px 6px;font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;
  -moz-appearance:textfield}
.board.dayreport.transfer input.gotbox::-webkit-outer-spin-button,
.board.dayreport.transfer input.gotbox::-webkit-inner-spin-button{
  -webkit-appearance:none;margin:0}
.board.dayreport.transfer tr.quiet input.gotbox{background:var(--panel)}
.board.dayreport.transfer .dt{min-width:120px}
/* Today. On a month-long range it is one row in thirty, and it is the row
   somebody opened the report to read. Marked, not shouted at — the loud colours
   on this table are reserved for money that is wrong. */
.board.dayreport tbody tr.now td{background:var(--accent-soft);
  border-top:1px solid var(--accent);border-bottom:1px solid var(--accent)}
.board.dayreport tbody tr.now .dt{background:var(--accent-soft);font-weight:700;
  box-shadow:1px 0 0 var(--accent)}
.board.dayreport tbody tr.now .todaymark{margin-left:7px;font-size:8px;
  letter-spacing:.13em;text-transform:uppercase;color:var(--accent);font-weight:600}
.board.report td.dim{color:var(--faint)}
.board.report tr.shut td{background:var(--sunk);color:var(--faint)}
.board.report td.dim{color:var(--faint)}
.board.report tr.shut td{background:var(--sunk);color:var(--faint)}

/* ===========================================================================
   The oven board — one tile per cake, five to a row.
   A baker reads this across a room, so the two things that decide what happens
   next are the biggest: the hour it has to be out, and whether it is done.
   =========================================================================== */
.ovengrid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:10px;
  margin-top:12px;align-items:stretch}
/* Five holds all the way down to a 1024-wide screen — a counter monitor is
   often 1366, and dropping to four there would be four when five was asked for.
   Below that there is genuinely not room. */
@media (max-width:1000px){.ovengrid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:760px){.ovengrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.ovengrid{grid-template-columns:1fr}}

/* Two things happen to a cake here and they are different facts, so they are
   two targets: the body of the tile is BAKED, the foot is HANDED OVER. */
.oven{display:flex;flex-direction:column;border:1px solid var(--line);
  border-left:3px solid var(--line2);border-radius:4px;background:var(--panel);
  color:var(--ink);overflow:hidden;transition:opacity .12s,border-color .12s}
.oven:hover{border-color:var(--accent)}
.oven-bake{display:flex;flex-direction:column;gap:6px;text-align:left;font:inherit;
  flex:1 1 auto;padding:10px 10px 8px;border:0;border-radius:0;background:none;
  color:inherit;cursor:pointer}
.oven-bake:hover{background:var(--accent-soft)}
.oven-bake:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
/* The second click, and only where the unit is the collection point. */
.oven-hand{font:inherit;font-size:10px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;font-family:"IBM Plex Mono",monospace;
  padding:6px 10px;border:0;border-top:1px solid var(--line);border-radius:0;
  background:var(--sunk);color:var(--dim);cursor:pointer;text-align:center}
.oven-hand:hover{background:var(--accent);color:var(--accent-ink)}
.oven-hand.on{background:var(--ink);color:var(--panel)}
.oven-hand.on:hover{background:var(--accent);color:var(--accent-ink)}
/* Gone: the customer has it, and it is no longer anybody's job.
   NOT opacity. The shop: "The lavender background is over the text and not
   under the text, hence the text on it is not clear." Exactly what opacity on
   a card does — it composites the whole tile, TEXT INCLUDED, toward whatever
   is behind it, so the tint appears to wash over the words instead of sitting
   under them. A finished cake is dimmed by colour now, and the words stay
   words. */
.oven.gone{border-left-color:var(--ink);background:var(--sunk)}
/* Eggless changes what goes in the bowl, so it marks the whole tile — but the
   two that change where the cake GOES, or how much work it is, outrank it. */
.oven.eggless{border-left-color:var(--ok)}
.oven.hot{border-left-color:var(--crit)}
.oven.deliver{border-left-color:var(--berry);
  background:color-mix(in srgb, var(--berry) 5%, var(--panel))}
/* Yeyyadi has its own oven, so a Yeyyadi order on the Production Unit's board
   is an overflow — made here, and then it has to travel back. The whole tile
   changes ground, because it is a fact about the cake and not about one field
   on it. It sits after .deliver so a Yeyyadi delivery still reads as Yeyyadi;
   the berry left border keeps saying delivery. .done outranks both. */
/* A cake for the OTHER shop. See the note in kitchen.js: a lavender tint at
   arm's length across a kitchen is not a colour, it is a slightly different
   white. A band across the top with the shop's name in it, and a solid edge
   down the side, so it can be picked out of forty tiles without reading one. */
.oven.fromyey{background:var(--yey-soft);border-color:var(--yey-line);
  border-left-color:var(--yey-line);border-left-width:6px}
.oven.fromyey .oven-hand{background:color-mix(in srgb, var(--yey-line) 12%, var(--yey-soft))}
.oven-flag{display:flex;align-items:baseline;gap:8px;
  padding:4px 10px;background:var(--yey-line);color:#FFF;
  font-family:"IBM Plex Mono",monospace;font-size:10px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase}
.oven-flag span{margin-left:auto;font-weight:500;letter-spacing:.06em;
  text-transform:none;opacity:.85}
.oven.fromyey.done{border-left-color:var(--ok)}
.oven.fromyey.done .oven-flag{background:var(--line2);color:var(--dim)}
.oven.done{border-left-color:var(--ok);background:var(--sunk)}
/* One rule for both finished states: quieter type, never see-through type. */
.oven.done,.oven.gone{color:var(--dim)}
.oven.done .oven-name,.oven.gone .oven-name,
.oven.done .oven-msg,.oven.gone .oven-msg,
.oven.done .oven-who,.oven.gone .oven-who,
.oven.done .oven-info.note,.oven.gone .oven-info.note{color:var(--dim)}
.oven.done .oven-time,.oven.gone .oven-time{color:var(--faint)}
.oven.done .oven-pills .pill,.oven.gone .oven-pills .pill{opacity:.75}
/* A finished cake for the other shop keeps its lavender, muted — the band goes
   grey so it stops shouting for attention it no longer needs. */
.oven.fromyey.done,.oven.fromyey.gone{
  background:color-mix(in srgb, var(--yey-soft) 55%, var(--sunk))}

.oven-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.oven-time{font-family:"IBM Plex Mono",monospace;font-size:15px;font-weight:600;
  font-variant-numeric:tabular-nums}
.oven-time.early{color:var(--crit)}
/* Empty until it is baked: an empty circle is the thing left to do. */
.oven-tick{width:22px;height:22px;flex:0 0 auto;border-radius:50%;
  border:1.5px solid var(--line2);display:grid;place-items:center;
  font-size:13px;font-weight:700;color:transparent}
.oven-tick.on{background:var(--ok);border-color:var(--ok);color:#FFF}

.oven-cake{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}
.oven-code{font-family:"IBM Plex Mono",monospace;font-size:11px;color:var(--accent)}
.oven-name{font-family:Fraunces,Georgia,serif;font-size:15px;font-weight:700;
  line-height:1.15;flex:1 1 auto;min-width:0}
.oven-of{font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint)}
/* What actually gets piped onto the cake, in the face the shop writes in. */
.oven-msg{font-family:Fraunces,Georgia,serif;font-size:14px;line-height:1.3;
  color:var(--ink)}
.oven-pills{display:flex;gap:4px;flex-wrap:wrap}
.oven-pills:empty{display:none}
.oven-info{font-size:11px;color:var(--dim);background:var(--sunk);
  border-left:2px solid var(--line2);border-radius:4px;padding:4px 6px;
  white-space:normal}
/* The one the baker was told to read. It is not a footnote — somebody typed it
   because the cake is not standard, so it carries the weight of the message. */
.oven-info.note{font-weight:700;color:var(--ink)}
.oven-cap{font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint);margin-bottom:2px}
/* Who to ring. The unit holds the cake and is often the last place able to. */
.oven-who{font-size:11px;line-height:1.35;color:var(--ink)}
.oven-who b{font-weight:700}
.oven-who .num{font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums;
  color:var(--dim)}
.oven-foot{margin-top:auto;padding-top:2px;font-size:10px;color:var(--faint)}

/* THREE GROUPS UNDER EACH SHOP. What is on the shelf, what is on the counter to
   eat, and what is boxed with somebody's name on it — three different questions,
   which used to be one flat list sorted by code. */
.stockgroup + .stockgroup{margin-top:14px}
/* Three questions, three boxes. See the note in counters.js. */
.counterset{display:flex;flex-direction:column;gap:12px}
.counterset > .panel{margin-top:0}
.stockbox .phead h2{font-size:13px}
.stockhead{display:flex;align-items:baseline;gap:8px;margin-bottom:7px;
  font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--faint);
  border-bottom:1px solid var(--line);padding-bottom:4px}
.stockhead .r{margin-left:auto;font-size:11px;letter-spacing:0;color:var(--dim);
  font-weight:600}

/* ---- at the counters: one tile per cake, same idea as the oven board ----- */
.stockgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));
  gap:8px}
.stock{display:flex;flex-direction:column;gap:3px;padding:8px 10px;
  border:1px solid var(--line);border-left:3px solid var(--line2);
  border-radius:4px;background:var(--panel)}
.stock.out{border-left-color:var(--crit);background:var(--crit-soft)}
.stock-top{display:flex;align-items:center;justify-content:space-between;gap:6px}
.stock-code{font-family:"IBM Plex Mono",monospace;font-size:11px;color:var(--accent)}
.stock.out .stock-code{color:var(--crit)}
.stock-size{font-family:"IBM Plex Mono",monospace;font-size:10px;
  background:var(--accent-soft);color:var(--accent);border:1px solid var(--line2);
  border-radius:4px;padding:0px 4px;white-space:nowrap}
.stock-name{font-family:Fraunces,Georgia,serif;font-size:13px;font-weight:700;
  line-height:1.2}
/* The quantity decides whether somebody bakes more, so it is the biggest thing
   on the tile — and a zero says the words rather than showing a small 0. */
.stock-qty{display:flex;align-items:baseline;gap:6px;margin-top:auto;padding-top:4px}
.stock-qty b{font-family:Fraunces,Georgia,serif;font-size:26px;line-height:1}
.stock-out{font-family:"IBM Plex Mono",monospace;font-size:10px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--crit);font-weight:700}
.stock-sold{font-size:10px;color:var(--faint)}

/* ===========================================================================
   Office cash — the tin, what leaves it, and the notes counted against it.
   Two four-column tables side by side, and a note pad along the foot. Nothing
   here is wide: the whole point of dropping the per-day count was that four
   columns fit in half the screen and two books can be read together.
   =========================================================================== */
/* Four figures across the top, in the order the arithmetic runs. Read left to
   right they are a sentence: had this, got this, paid that, so this is left. */
.tin{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;
  margin:14px 0 0}
.tinbit{background:var(--panel);border:1px solid var(--line);border-radius:8px;
  padding:8px 12px;display:flex;flex-direction:column;gap:2px}
.tinbit span{font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--faint)}
.tinbit b{font-size:19px;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.tinbit.up b{color:var(--ok)}
.tinbit.down b{color:var(--crit)}
/* The one the pad below is checked against. */
.tinbit.now{background:var(--accent-soft);border-color:var(--accent)}
.tinbit.now span{color:var(--accent)}
.tinbit.now b{font-size:21px}

/* The two books. Equal halves — they are the same shape and are read across. */
.twoup{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;
  align-items:start;margin-top:14px}
@media (max-width:1000px){.twoup{grid-template-columns:minmax(0,1fr)}}
.twoup .panel.half{margin-top:0;min-width:0}
/* Both lists can run to a month. Scrolling them inside the panel keeps the pad
   at the foot on screen, which is where the answer is. */
.scroll.tall{max-height:460px;overflow-y:auto}

/* .board carries a 1540px floor for the thirteen-column day board. These two
   have four columns each and live in half the width; inheriting that floor
   pushed the balance off the right-hand edge into a scroll nobody would drag. */
.board.tinbook,.board.spends{min-width:0;table-layout:auto}
.board.tinbook .dt,.board.spends .dt{width:70px;white-space:nowrap}
.board.tinbook td,.board.spends td{padding-top:4px;padding-bottom:4px}
.board.tinbook th.tr,.board.tinbook td.tr{width:33%}
.board.spends td.what{white-space:normal;line-height:1.35}
.board.spends th:nth-child(3),.board.spends td:nth-child(3){width:92px;white-space:nowrap}
.board.spends th:nth-child(4),.board.spends td:nth-child(4){width:30px}
.board .sub{color:var(--faint);font-size:11px;display:block}
.board .sub.crit{color:var(--crit)}
.board tbody tr.quiet td{color:var(--faint)}
/* An × rather than the word "cancel": the word was wider than the amount. */
.xout{background:none;border:0;padding:0 2px;font:inherit;font-size:15px;line-height:1;
  color:var(--line2);cursor:pointer}
.xout:hover{color:var(--crit)}

/* Recording a payment: one line, so it never reads as a form to fill in. */
.spendrow{display:flex;flex-wrap:wrap;gap:6px;align-items:center;
  padding:10px 0 8px;border-bottom:1px solid var(--line)}
.spendrow input[type=text]{flex:1 1 100px;min-width:90px}
.spendrow select{flex:1 1 150px;min-width:140px}
.spendrow button{margin-left:auto}

/* ------------------------------------------------------------- the note pad --
   A calculator, not a report: nine cells in a row, the total and the verdict
   under them. It is checked against "Should be there" above — the tin is
   counted on a random Tuesday, so there is no per-day column for it. */
.padpanel{margin-top:14px}
.padcells{display:grid;grid-template-columns:repeat(9,minmax(0,1fr));gap:8px;
  padding:14px 0 4px}
@media (max-width:820px){.padcells{grid-template-columns:repeat(3,minmax(0,1fr))}}
.padcell{display:flex;flex-direction:column;gap:3px;margin:0;min-width:0}
.padcell .mono{font-size:11px;color:var(--dim);text-align:center}
.padcell input{width:100%;text-align:center;padding:6px 4px;font-size:15px;
  font-variant-numeric:tabular-nums;-moz-appearance:textfield}
.padcell input::-webkit-outer-spin-button,
.padcell input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.padcell i{font-style:normal;font-size:11px;color:var(--faint);text-align:center;
  min-height:15px;font-variant-numeric:tabular-nums}
.padfoot{display:flex;flex-wrap:wrap;align-items:center;gap:14px;
  padding-top:10px;border-top:1px solid var(--line);margin-top:6px}
.padfoot .ct{display:flex;align-items:baseline;gap:8px;font-size:11px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}
.padfoot .ct b{font-size:21px;letter-spacing:-.01em;color:var(--ink);
  font-variant-numeric:tabular-nums;text-transform:none;letter-spacing:normal}
.padsay{font-size:14px;color:var(--dim)}
.padsay b{font-weight:700}
.padgo{margin-left:auto;display:flex;align-items:center;gap:8px}

/* ===========================================================================
   Deliveries — the fee beside what the driver cost.
   =========================================================================== */
.board.runs{min-width:0;table-layout:auto}
.board.runs .dt{width:74px;white-space:nowrap}
.board.runs td.ref,.board.runs th:nth-child(2){width:160px;white-space:nowrap;
  font-size:12px;color:var(--dim)}
.board.runs td.what{white-space:normal;line-height:1.35;min-width:220px}
.board.runs th:nth-child(4),.board.runs td:nth-child(4){width:96px;white-space:nowrap}
.board.runs th:nth-child(5),.board.runs td:nth-child(5){width:104px}
.board.runs th:nth-child(6),.board.runs td:nth-child(6){width:126px}
.board.runs th:nth-child(7),.board.runs td:nth-child(7){width:110px;white-space:nowrap}
.board.runs td{padding-top:6px;padding-bottom:6px}
/* Typed straight into the row it belongs to, like the office's receipts. */
.board.runs input.costbox{width:100%;text-align:right;padding:3px 6px;
  font-size:12px;font-weight:600;font-variant-numeric:tabular-nums;
  -moz-appearance:textfield}
.board.runs input.costbox::-webkit-outer-spin-button,
.board.runs input.costbox::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.board.runs input.whobox{width:100%;padding:3px 6px;font-size:12px}
.board.runs tr.quiet td{color:var(--faint);background:var(--sunk)}
/* Why the three figures in the strip do not subtract to each other. */
.tinbit .onlyon{font-style:normal;font-size:11px;color:var(--faint);
  text-transform:none;letter-spacing:normal;margin-top:1px}

/* ===========================================================================
   Admin — reference data. Dense tables, one editor panel above them.
   =========================================================================== */
.adminbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;
  padding:12px 0 10px;border-bottom:1px solid var(--line);margin-bottom:2px}
/* Inputs in this app stretch by default; on a one-line bar they have to not. */
.adminbar > input,.adminbar > select{flex:0 0 auto}
.adminbar .field,.prodform .field,.setprices .field{display:flex;align-items:center;gap:6px}
.adminbar label.tick,.prodform label.tick{display:flex;align-items:center;gap:6px;
  font-size:13px;color:var(--dim);white-space:nowrap;margin:0}
.adminbar label.tick input,.prodform label.tick input{width:auto;margin:0}

.board.cat{min-width:0;table-layout:auto}
.board.cat td,.board.cat th{padding-top:6px;padding-bottom:6px}
.board.cat td.code{width:130px;white-space:nowrap;font-size:12px}
.board.cat td.code .half{font-style:normal;color:var(--faint);font-size:11px;
  margin-left:7px}
.board.cat tbody tr.quiet td{color:var(--faint)}
.odd{font-style:normal;font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--warn);margin-left:7px}
.per{font-style:normal;font-size:10px;color:var(--faint);margin-left:2px}
.queued{font-size:10px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--warn)}

/* The one product being worked on, above the list it came from. */
.editor{background:var(--sunk);border:1px solid var(--line2);border-radius:8px;
  padding:4px 14px 14px;margin:12px 0 4px}
.phead.thin{padding-top:12px}
.prodform{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:6px 0 12px;
  border-bottom:1px solid var(--line)}
.prodform button{margin-left:auto}
.prodform input,.prodform select{background:var(--panel)}

.board.pricetab{min-width:0;table-layout:auto}
.board.pricetab .dt{width:150px;white-space:nowrap}
.board.pricetab td,.board.pricetab th{padding-top:4px;padding-bottom:4px}
.setprices{display:flex;flex-wrap:wrap;gap:10px;align-items:center;padding:12px 0 4px}
.setprices button{margin-left:auto}
.setprices input{background:var(--panel)}
.setprices input[type=number]{-moz-appearance:textfield}
.setprices input[type=number]::-webkit-outer-spin-button,
.setprices input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.adminbar input[type=number]{-moz-appearance:textfield}
.adminbar input[type=number]::-webkit-outer-spin-button,
.adminbar input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}

/* What the per-kg rate works out to, every rung editable so a cake is still
   allowed an odd price at 2.5 kg. */
.ladderwrap{display:flex;align-items:flex-start;gap:10px;padding:6px 0 2px;flex-wrap:wrap}
.ladder{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px;flex:1 1 400px}
@media (max-width:820px){.ladder{grid-template-columns:repeat(4,minmax(0,1fr))}}
.rung{display:flex;flex-direction:column;gap:3px;margin:0;min-width:0}
.rung .mono{font-size:11px;color:var(--faint);text-align:center}
.rung input{width:100%;text-align:center;padding:4px 4px;font-size:13px;
  background:var(--panel);font-variant-numeric:tabular-nums;-moz-appearance:textfield}
.rung input::-webkit-outer-spin-button,
.rung input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.rung input.edited{border-color:var(--accent);font-weight:600}

input.inline{width:100%;max-width:280px;padding:3px 6px;font-size:13px;
  background:transparent;border-color:transparent}
input.inline:hover,input.inline:focus{background:var(--panel);border-color:var(--line2)}

.note.warn{background:var(--warn-soft);border:1px solid var(--warn);
  border-radius:8px;padding:10px 12px;margin:12px 0 2px;font-size:13px;
  color:var(--warn)}
.note.warn b{display:block;font-size:14px;margin-bottom:2px}
/* A verb that reads as a link rather than a button: "retire" is a rare, quiet
   action at the end of a row, not something to invite a click on. */
.linky{background:none;border:0;padding:0;font:inherit;font-size:11px;
  color:var(--faint);cursor:pointer;text-decoration:underline}
.linky:hover{color:var(--crit)}
/* Sortable headings on the catalogue, the same gesture as the registers. */
.board.cat th.sortable{cursor:pointer;user-select:none;white-space:nowrap}
.board.cat th.sortable:hover{color:var(--ink)}
.board.cat th.sortable.on{color:var(--accent)}
.board.cat th.sortable i{font-style:normal;font-size:9px}
.adminbar .r{margin-left:auto}
.adminbar .found{font-size:12px;white-space:nowrap}
/* Closing an editor without saving. */
.phead .xout.close{margin-left:12px;font-size:19px;color:var(--faint)}
.phead .xout.close:hover{color:var(--crit)}
/* The name a number is saved under. Shown, never typed — BCH's customer list
   is kept against phone numbers. */
input.shown{background:var(--sunk);color:var(--dim);cursor:default}
input.shown:focus{outline:none;border-color:var(--line)}

/* ===========================================================================
   Which bill? Two documents come off the Print button and only the person at
   the window knows which moment it is.
   =========================================================================== */
/* ABOVE THE PANEL, not behind it. The "which document?" card is asked FROM
   inside an open bill, and at z-index 60 it opened underneath a sheet sitting
   at 400 — so pressing Print appeared to do nothing at all, with the question
   waiting out of sight. */
.askback{position:fixed;inset:0;z-index:600;background:rgba(20,10,8,.45);
  display:grid;place-items:center;padding:20px}
.askcard{background:var(--panel);border:1px solid var(--line2);border-radius:8px;
  box-shadow:0 18px 60px -20px rgba(0,0,0,.5);padding:20px;width:min(420px,100%);
  display:flex;flex-direction:column;gap:10px}
.askcard h2{margin:0 0 4px;font-size:17px}
.billpick{display:flex;flex-direction:column;align-items:flex-start;gap:3px;
  text-align:left;padding:12px 14px;border:1px solid var(--line2);border-radius:8px;
  background:var(--sunk);cursor:pointer;font:inherit;color:var(--ink);width:100%}
.billpick:hover,.billpick:focus-visible{border-color:var(--accent);
  background:var(--accent-soft);outline:none}
.billpick b{font-size:15px}
.billpick span{font-size:12px;color:var(--dim);line-height:1.4}
.askcard .ghost{align-self:flex-end;margin-top:2px}
/* What the number will actually dial. Sits under the saved-contact line. */
.hint.dial{font-size:11px;line-height:1.4;margin-top:2px}

/* ===========================================================================
   Taking a report away — the bar under it, and what the printer sees.
   =========================================================================== */
/* THE WAY OUT STAYS ON THE SCREEN. A hundred-row report put Save as PDF a
   hundred rows down, so the one control somebody came for was the one they had
   to go looking for. It sticks to the bottom of the page instead, above the
   money bar, and stops looking stuck the moment the report is short enough to
   fit. */
.takeaway{display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  padding:12px 14px 10px;margin-top:12px;border-top:1px solid var(--line);
  position:sticky;bottom:0;z-index:12;
  background:var(--panel);
  box-shadow:0 -10px 18px -14px rgba(0,0,0,.5)}

/* Capped and centred. See the note on register() — a report is narrow unless
   it genuinely reads across. */
.repnarrow{max-width:1280px;margin-left:auto;margin-right:auto}

/* The day board's cake cell, on two lines. See the note in dayboard.js: the
   marks trailing off to the right of the size had to be hunted for; on a line
   of their own the state of every cake reads straight down the column. */
td.cake{white-space:normal}
td.cake .cpills{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}
td.cake .cpills .pill{margin-left:0 !important}

/* A figure you can press. Both of these were hovers, and a hover is a fact you
   cannot read twice — and does not exist at all on the counter's touchscreen. */
td.tap{cursor:pointer;text-decoration:underline;
  text-decoration-style:dotted;text-underline-offset:3px;
  text-decoration-color:var(--faint)}
td.tap:hover{color:var(--accent);text-decoration-color:var(--accent)}
.addrbox{white-space:pre-wrap;font-size:13px;line-height:1.55;padding:8px 10px;
  border:1px solid var(--line);border-radius:6px;background:var(--ground)}

/* Hover to read the whole of it. See the note in ui.js — the browser's own
   tooltip takes the best part of a second, comes up grey on grey in a face
   nobody chose, and the counter reading a message down the telephone wants it
   now and wants it legible. */
.hovernote{position:fixed;z-index:700;max-width:340px;
  background:var(--ink);color:var(--ground);
  font-family:Fraunces,Georgia,serif;font-size:14px;line-height:1.35;
  padding:8px 10px;border-radius:6px;white-space:pre-wrap;
  box-shadow:0 10px 26px -8px rgba(0,0,0,.55);pointer-events:none}
.hovernote[hidden]{display:none}

/* What gets piped onto the cake, in the face it is piped in. */
.msgedit textarea,.msgedit input,.msgread{font-family:Fraunces,Georgia,serif;
  font-size:16px;line-height:1.35;width:100%}
.msgread{padding:8px 10px;border:1px solid var(--line);border-radius:6px;
  background:var(--ground);min-height:52px;white-space:pre-wrap}

/* The bill as it will come out of the printer, on the screen first. The slip is
   drawn at 80mm for thermal paper, so it is centred on a plain ground rather
   than stretched across a panel it was never designed for. */
.billpreview{display:flex;justify-content:center;padding:14px;
  background:var(--sunk);border:1px solid var(--line);border-radius:6px;
  max-height:62vh;overflow:auto}
.previewcard{width:auto;max-width:min(94vw,560px)}
.previewcard h2{display:flex;align-items:baseline;gap:10px}
.previewcard h2 .sub{font-size:12px;font-weight:400;color:var(--dim);
  font-family:"IBM Plex Mono",monospace}
.billpreview .bill{background:#FFF;color:#111;box-shadow:0 2px 14px rgba(0,0,0,.18)}

/* ===========================================================================
   A CANCELLED BILL, OPENED. It is a record and not a form: stamped across,
   locked, and the only way out of it is to put it back.

   The stamp goes OVER the bill, as a stamp does — but at a tenth of full
   strength and drawn as an outline, so it reads as ink on the page rather than
   as something painted across the words. Nothing here touches the opacity of
   the content itself; that is the mistake that made the lavender tiles
   unreadable.
   =========================================================================== */
.cancelled-bill{position:relative}
.cancelled-bill::after{
  content:'CANCELLED';
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-family:"IBM Plex Mono",monospace;font-weight:700;letter-spacing:.18em;
  font-size:clamp(52px,9vw,150px);line-height:1;
  color:color-mix(in srgb, var(--crit) 11%, transparent);
  -webkit-text-stroke:2px color-mix(in srgb, var(--crit) 22%, transparent);
  transform:rotate(-14deg);
  pointer-events:none;z-index:6;user-select:none;white-space:nowrap}
/* Locked, and it looks locked. The controls are genuinely disabled — a
   pointer-events lock leaves every box reachable by the Tab key. */
.cancelled-bill input,
.cancelled-bill select,
.cancelled-bill textarea{background:var(--sunk);color:var(--dim);
  cursor:not-allowed}
.cancelled-bill button{cursor:not-allowed}
.cancelled-bill .panel{background:color-mix(in srgb, var(--crit) 3%, var(--panel))}

/* A cancelled bill stays on the statement and is struck through. It happened,
   the customer remembers it, and the money that went against it is the reason
   he is holding a credit — but it is not a sale and it is not added up. */
.board.report tr.struck td{text-decoration:line-through;
  text-decoration-color:var(--crit);text-decoration-thickness:1px;
  color:var(--dim)}
.board.report tr.struck td .pill{text-decoration:none}

/* ===========================================================================
   REPORTS: a rail down the left, a thin bar across the top.
   Thirteen report names in a row wrapped onto two lines and read as a wall.
   Down the left, grouped under the question each group answers, they read as a
   contents page — and the one you are on stays visible while the report
   scrolls, which a wrapping tab row never managed.
   =========================================================================== */
.repwrap{display:grid;grid-template-columns:186px minmax(0,1fr);gap:16px;
  margin-top:14px;align-items:start}
.repnav{position:sticky;top:12px;max-height:calc(100vh - 90px);overflow:auto;
  background:var(--panel);border:1px solid var(--line);border-radius:6px;
  padding:6px 0 10px;scrollbar-gutter:stable}
.repnav a{display:block;padding:6px 14px;font-size:13px;color:var(--ink);
  text-decoration:none;border-left:2px solid transparent}
.repnav a:hover{background:var(--accent-soft);color:var(--accent)}
.repnav a.on{background:var(--accent-soft);color:var(--accent);font-weight:600;
  border-left-color:var(--accent)}
.repgroup{font-family:"IBM Plex Mono",monospace;font-size:9px;
  letter-spacing:.13em;text-transform:uppercase;color:var(--faint);
  padding:12px 14px 4px}
.repnav-item:first-child .repgroup{padding-top:6px}

.reppane{min-width:0}
.repbar{display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  background:var(--panel);border:1px solid var(--line);border-radius:6px;
  padding:8px 10px}
.repbar .spacer{flex:1 1 auto}
.repwhen{font-size:12px;padding:4px 8px;font-weight:600;
  flex:0 0 auto;width:auto;min-width:130px}
.repbar input[type=date]{font-size:12px;padding:4px 6px;flex:0 0 auto;width:auto}
/* A select in the bar sizes to its content. Without this it takes the flex
   line's whole width and drops the rest of the bar onto a second row. */
.repbar select{flex:0 0 auto;width:auto}
.repbar .hlbl{flex:0 0 auto}
.repbar .nav{flex:0 0 auto}
.repstats{min-height:18px;padding:8px 2px 0;font-size:11px;color:var(--dim);
  text-align:right}

/* Three marks, not three sentences. */
.repicons{display:flex;gap:6px;align-items:center}
.repicon{display:inline-flex;align-items:center;justify-content:center;
  width:32px;height:30px;padding:0;border-radius:6px}
.repicon:hover{border-color:var(--accent);color:var(--accent);
  background:var(--accent-soft)}

@media (max-width:1000px){
  .repwrap{grid-template-columns:minmax(0,1fr)}
  .repnav{position:static;max-height:none;display:flex;flex-wrap:wrap;
    padding:6px}
  .repnav .repgroup{width:100%;padding:6px 8px 2px}
  .repnav a{border-left:0;border-radius:4px}
}

/* "1 cake", not "1" over "cakes". */
.board.report td.nowrap{white-space:nowrap}
.board.report td .sub.unit{margin-left:5px;white-space:nowrap;display:inline}
.takeaway .note{font-size:11px;color:var(--faint);margin-left:auto}
/* Pills. Three ways out of the same report, so they read as one set of three
   rather than as three unrelated buttons — same size, same shape, side by side,
   and round enough that nothing about them looks like the primary action on the
   screen. Saving a copy never is. */
.takeaway button{border-radius:999px;padding:6px 16px;font-size:12px;
  font-weight:500;border:1px solid var(--line2);background:var(--panel);
  color:var(--dim);cursor:pointer;white-space:nowrap;
  transition:border-color .12s,color .12s,background .12s}
.takeaway button:hover{border-color:var(--accent);color:var(--accent);
  background:var(--accent-soft)}
.takeaway button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.takeaway button:active{transform:translateY(1px)}
.printcap{display:none}

@media print{
  /* Everything that is a control rather than a figure. A printed report is
     read on paper, where a date picker is a grey box that means nothing. */
  html.printing-report .bar,
  html.printing-report .panel > .phead,
  html.printing-report .takeaway,
  html.printing-report .headmenu,
  html.printing-report .toast,
  html.printing-report .party{display:none !important}

  html.printing-report .printcap{display:block;margin:0 0 10px}
  html.printing-report .printcap b{display:block;font-size:15px}
  html.printing-report .printcap span{font-size:12px;color:#444}
  html.printing-report .printcap i{font-style:normal;font-size:12px;color:#444;
    margin-left:10px}

  /* On screen the long tables scroll inside their panel. On paper there is no
     scrolling — the rest of the rows would simply be missing. */
  html.printing-report .scroll,
  html.printing-report .scroll.tall{max-height:none !important;overflow:visible !important}
  html.printing-report .panel{border:0;box-shadow:none;padding:0;margin:0 0 14px;
    background:#fff;break-inside:auto}
  html.printing-report .twoup{display:block}
  html.printing-report .tin{break-inside:avoid}

  /* The heading repeats at the top of every page, and no row is cut in half. */
  html.printing-report table{width:100% !important;min-width:0 !important;
    font-size:10px;border-collapse:collapse}
  html.printing-report thead{display:table-header-group}
  html.printing-report tfoot{display:table-footer-group}
  html.printing-report tr{break-inside:avoid}
  html.printing-report td,html.printing-report th{padding:3px 4px}
  /* A typed figure has to print as a figure, not as an empty box outline. */
  html.printing-report input{border:0 !important;background:transparent !important;
    padding:0 !important;color:#000 !important;font-size:10px}
  html.printing-report button{display:none !important}
}
/* Bill numbers are BCH/YEY/2026/00001 now — long, and never to be wrapped in
   the middle, because half a bill number is not a bill number. */
.board.report td.ref,.board.runs td.ref{white-space:nowrap;font-size:11px;
  overflow:hidden;text-overflow:ellipsis}

/* ===========================================================================
   On a phone.
   =========================================================================== */
/* BCH360 is desktop software and stays desktop software — the counters work on a
   monitor and that is what the layout is for. This is the OWNER's phone: a call
   comes in, an order goes on, and the day gets looked at. Two screens, not
   seven, and the same code underneath so the half-kg premium and the eggless
   charge cannot drift between the two.
   =========================================================================== */
@media (max-width: 760px){

  /* ------------------------------------------------------------- the band --
     Seven tabs will not fit across a phone and wrapping them costs three lines
     of a small screen. So the strip scrolls sideways, and everything else on
     the band sits above it on one line. */
  .bar{flex-wrap:wrap;padding:8px 10px;gap:8px}
  /* min-width:0 is the whole trick. A flex item will not shrink below the
     width of its contents however much overflow it is given, so without this
     the seven tabs push the band — and the page — wider than the phone. */
  .bar nav.nav{order:3;width:100%;min-width:0;max-width:100%;overflow-x:auto;
    flex-wrap:nowrap;-webkit-overflow-scrolling:touch;scrollbar-width:none;
    padding-bottom:2px}
  .bar>*{min-width:0}
  .bar nav.nav::-webkit-scrollbar{display:none}
  .bar nav.nav a{flex:0 0 auto;white-space:nowrap}
  /* The two a phone is for, first. Nothing is hidden — the strip scrolls and
     everything else is still behind it — but taking an order and looking at the
     day are what somebody opens this on a phone to do, and they should not have
     to swipe to find either. */
  .bar nav.nav a[href^="#/order"]{order:-2}
  .bar nav.nav a[href^="#/board"]{order:-1}
  /* Room for the home bar on a phone with no button. */
  body{padding-bottom:env(safe-area-inset-bottom)}
  .bar .tgt{order:2;margin-left:auto}
  .bar .who{font-size:11px}
  main{padding:0 10px 28px}
  .panel{padding:10px}

  /* -------------------------------------------------- a cake, on a phone --
     The cake table is fifteen columns and 1626px wide. On a phone that is not a
     table that needs scrolling, it is a form that cannot be filled in: the size
     and the quantity are off the right-hand edge, so an order literally cannot
     be completed. Each row becomes a card instead, two fields across. */
  .xscroll{overflow:visible;margin:0;padding:0}
  .cakes{min-width:0;table-layout:auto;display:block}
  .cakes colgroup,.cakes thead{display:none}
  .cakes tbody{display:block}
  .cakes tbody tr{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    gap:8px 10px;position:relative;
    background:var(--panel);border:1px solid var(--line);border-radius:8px;
    padding:12px 12px 12px;margin:0 0 10px}
  /* Every sticky offset is meaningless once there are no columns to scroll. */
  .cakes th:nth-child(1),.cakes td:nth-child(1),
  .cakes th:nth-child(2),.cakes td:nth-child(2),
  .cakes th:nth-child(3),.cakes td:nth-child(3){position:static;left:auto;box-shadow:none}
  .cakes tbody tr:nth-child(n) td:nth-child(-n+3){background:transparent;z-index:auto}
  .cakes tbody td{display:block;padding:0;height:auto;border:0;white-space:normal}
  /* A column with nothing in it — a pastry has no shape, no topper, no message —
     takes no room rather than leaving a labelled hole. */
  .cakes tbody td:empty,.cakes tbody td.nix{display:none}
  .cakes tbody td::before{content:attr(data-label);display:block;
    font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.11em;
    text-transform:uppercase;color:var(--faint);margin-bottom:3px}
  .cakes tbody td:not([data-label])::before{content:none}
  .cakes input,.cakes select{font-size:16px;padding:8px 10px;width:100%}
  /* 16px is not a taste: anything smaller and iOS zooms the whole page in when
     the box is tapped, and never zooms back out. */
  .cakes td.tc{text-align:left}
  .cakes td.tc input[type=checkbox]{width:auto;transform:scale(1.3);
    transform-origin:left center;margin:5px 0 0}
  /* The ones that need the whole width to be readable. */
  .cakes td[data-label="Cake"],
  .cakes td[data-label="Message on cake"],
  .cakes td[data-label="Dietary"],
  .cakes td[data-label="Additional info"]{grid-column:1 / -1}
  /* Remove-this-line, out of the way in the corner rather than in the flow. */
  .cakes tbody td:not([data-label]){position:absolute;top:6px;right:8px;
    grid-column:auto;width:auto}
  .cakes tbody td:not([data-label]) button{font-size:19px;padding:2px 8px}

  /* ------------------------------------------------- the rest of the form --
     The four panels are side by side on a monitor and stack on a phone, which
     the grid already does. What it does not do is make the boxes thumb-sized. */
  .grid,.grid3,.grid4,.grid.level{grid-template-columns:minmax(0,1fr)}
  .panel input,.panel select,.panel textarea{font-size:16px;padding:8px 10px}
  .picker{max-height:52vh}
  .picker .opt{padding:10px}
  /* The keyboard shortcut strip is a line of things a phone has no keys for. */
  .keys{display:none}

  /* ---------------------------------------------------------- the day board
     It already dropped to four columns and scrolled the rest away sideways,
     which meant the phone could not see whether a cake was ready or collected —
     the two things the board is opened to find out. */
  .board{min-width:0;table-layout:auto;font-size:13px}
  .board thead th{padding:6px 4px;font-size:9px}
  .board tbody td{padding:6px 4px}
  .board td.cake{min-width:0}

  /* Two thumbs, one screen. A save button that shares a line with "Start again"
     is a save button somebody misses. */
  .savebar{position:sticky;bottom:0;background:var(--ground);padding:8px 0;
    border-top:1px solid var(--line);z-index:5}
  .savebar button{padding:14px;font-size:15px}
  .savebar button.primary{flex:1 1 auto}
  /* Where the cake is baked sits beside the panel heading and its longest
     option — "Yeyyadi oven — cakes up to 1 kg only" — is wider than the phone.
     On its own line under the heading, full width. */
  .phead{flex-wrap:wrap;gap:6px}
  /* The wrapper is pushed to the right of the heading by margin-left:auto,
     which on a phone means it starts 37px in and runs off the end. Its own line
     instead, full width. */
  .phead>span:has(.bakedrow){width:100%;min-width:0;margin-left:0}
  .bakedrow{width:100%;min-width:0}
  .bakedrow select{flex:1 1 auto;width:100%;min-width:0}
}

/* ---------------------------------------------------------- what came in ---
   Under the day board: what each account TOOK on the day on screen. Not the
   sum of the columns above it — an advance for next Saturday is money that
   arrived today and a cake collected today may have been paid for a fortnight
   ago. Set apart from the table for exactly that reason. */
.tookrow{display:flex;flex-wrap:wrap;align-items:baseline;gap:16px;
  padding:10px 2px 2px;margin-top:10px;border-top:1px solid var(--line)}
.took{display:flex;align-items:baseline;gap:6px;white-space:nowrap}
.took i{font-style:normal;font-family:"IBM Plex Mono",monospace;font-size:9px;
  letter-spacing:.11em;text-transform:uppercase;color:var(--faint)}
.took b{font-variant-numeric:tabular-nums;font-size:14px}
.took b.nil{color:var(--faint);font-weight:400}
.took.total b{font-size:16px;color:var(--accent)}
/* Money that went back out. Already subtracted from every figure beside it, so
   it is coloured rather than sized — a warning, not a second total. */
.took.back b{color:var(--crit)}
.tookrow .r{margin-left:auto}
/* ------------------------------------------------ the party statement -- */
/* Five columns do not need a counter screen's width. A statement stretched
   across 1,600px puts four inches of nothing between the invoice number and
   the amount, which is exactly how a figure gets read against the wrong row. */
/* The statement was five columns and 700px was generous. It is eight now — the
   shop asked for the cake, how many and the message on it — so it gets the room
   those need and no more: a statement stretched across a counter screen puts
   four inches of nothing between the invoice number and the amount, which is
   exactly how a figure gets read against the wrong row. */
.narrow{max-width:1040px;margin:0 auto;display:flex;flex-direction:column;gap:12px}
.stmtpick .pbody{display:flex;flex-direction:column;gap:6px}
.stmtpick label{margin:0}
input.stmtfind{width:100%;padding:8px 10px;font-size:14px}
.stmthits{display:flex;flex-direction:column;gap:2px}
.stmthit{display:grid;grid-template-columns:1fr 92px 128px;gap:10px;align-items:baseline;
  padding:6px 8px;border-radius:4px;text-decoration:none;color:var(--ink)}
.stmthit:hover{background:var(--sunk)}
.stmthit b{font-weight:600}
.stmthit span{font-family:"IBM Plex Mono",monospace;font-size:11px;color:var(--faint)}
.stmthit i{font-style:normal;font-family:"IBM Plex Mono",monospace;font-size:11px;
  color:var(--dim);text-align:right}
/* Who they are, said once, so the table under it can be nothing but figures. */
.stmtwho{display:flex;flex-wrap:wrap;gap:18px;padding-bottom:10px;
  border-bottom:1px solid var(--line);margin-bottom:10px}
.stmtwho span{display:flex;flex-direction:column;gap:0px;font-size:13px}
.stmtwho i{font-style:normal;font-family:"IBM Plex Mono",monospace;font-size:9px;
  letter-spacing:.13em;text-transform:uppercase;color:var(--faint)}
.tin.stmttin{margin:0}
/* .board.report carries min-width:860px for the wide registers. A statement is
   five columns in a 700px column and must be allowed to be exactly that. */
.board.report.stmt{min-width:0}
.board.report.stmt tbody td,
.board.report.stmt tfoot td{font-size:13px}
/* The customer's name, at the size a name deserves. .phead h2 is a mono
   uppercase section label by convention here, which is the wrong dress for a
   person. */
.stmtname{font-family:Fraunces,Georgia,serif;font-size:21px;font-weight:700;
  letter-spacing:-.01em;line-height:1.15;margin-bottom:2px}
/* WHAT THE LINE IS, in the Status column of its own. This used to sit under the
   invoice number, where it read as part of the number.

   Money in reads green, money back out reads red, and a credit note is neither
   — the bill came down, nothing moved. Coloured on the word itself and not by
   position: the rules here were written as td:nth-child(3) and td:nth-child(4)
   and had been pointing at the wrong cells since a column was inserted in front
   of them, tinting the quantity instead of the amount. A selector that has to
   be recounted every time a column moves is a selector that will be wrong. */
.stmt .stmtstat{font-size:12px;font-weight:600;color:var(--dim)}
.stmt .stmtstat.in{color:var(--ok)}
.stmt .stmtstat.back{color:var(--crit)}
.stmt .stmtstat.cred{color:var(--warn)}
.stmt td.wrap{white-space:normal}
.stmt td.bal{font-weight:600}
.stmt tbody tr.cred td,.stmt tbody tr.back td{background:var(--sunk)}

/* Nine columns, one of them the message written on the cake. See partyReport. */
.stmtwide{max-width:1240px}

/* Two pills fit; a third wraps rather than pushing the row wider. */
td.paidby{white-space:normal;line-height:1.6}
td.paidby .pill{margin-right:4px}

/* --------------------------------------------- the closing count, five wide --
   Five figures across a third of the screen: the item column takes what is
   left and the numbers share the rest equally, so none of them is the runt.
   Below 560px the whole table scrolls in its own box rather than crushing the
   headings into ellipses. */
/* THE CLOSING TABLE — five figures beside the cake.
   Every heading is a whole word. "COUNT…" is not a column heading, it is a
   column heading that has given up: the counter reads it at the end of a long
   day and has to guess whether the box wants what she counted or what she is
   counting out. So the numeric columns are sized to the LONGEST heading rather
   than to the widest number, the padding tightens to buy the letters room, and
   the ellipsis is switched off so that if anything ever does overflow it shows
   as overflow instead of hiding itself politely.
   No min-width: the five figure columns are fixed at 64px and the cake name
   takes whatever is left, so the table fits any panel without ever scrolling
   sideways. A column you have to drag to reach is a column nobody reads, and
   the one that would hide is the difference. */
.board.shelf.close5 th{white-space:nowrap;overflow:visible;text-overflow:clip;
  padding-left:4px;padding-right:4px;text-align:right}
.board.shelf.close5 th:first-child{text-align:left;padding-left:8px}
.board.shelf.close5 tbody td{padding-left:4px;padding-right:4px}
.board.shelf.close5 tbody td:first-child{padding-left:8px}
.board.shelf.close5 input.bad{border-color:var(--crit);background:var(--crit-soft)}
.shelf-dest{display:inline-flex;align-items:center;gap:6px}
.note-edit select{font:inherit;font-size:13px;padding:4px 8px;border-radius:8px;
  border:1px solid var(--line2);background:var(--panel);color:var(--ink)}

/* ======================================================== THE DASHBOARD ======
   Its tab is deliberately NOT one of the nav pills. The nav is a picture of the
   working day and the dashboard is not a step in it, so it wears the gold
   instead of the white — the one other thing in the band that is about money,
   sitting next to the target it is measured against. */
.bar a.apart{font:inherit;font-size:12px;font-weight:600;text-decoration:none;
  padding:6px 12px;border-radius:4px;background:var(--gold);color:#2A1310;
  border:1px solid rgba(0,0,0,.14);white-space:nowrap;
  box-shadow:0 1px 2px rgba(0,0,0,.18)}
.bar a.apart:hover{filter:brightness(1.06)}
.bar a.apart.on{box-shadow:inset 0 0 0 2px rgba(0,0,0,.28)}
@media(max-width:760px){.bar a.apart{padding:6px 8px;font-size:11px}}

.dash{display:flex;flex-direction:column;gap:14px}
.dashhead{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.dashhead h1{margin:0;font-family:Fraunces,Georgia,serif;font-size:21px;font-weight:600}
/* A segmented control, not a dropdown: three choices all worth seeing, and the
   one you are on stays on screen. */
.seg{display:inline-flex;background:var(--sunk);border:1px solid var(--line);
  border-radius:6px;padding:2px;gap:2px}
.segbtn{font:inherit;font-size:12px;padding:6px 12px;border:0;border-radius:4px;
  background:transparent;color:var(--dim);cursor:pointer;white-space:nowrap}
.segbtn:hover{color:var(--ink)}
.segbtn.on{background:var(--panel);color:var(--ink);font-weight:600;
  box-shadow:0 1px 2px rgba(0,0,0,.12)}
.seg.small .segbtn{font-size:11px;padding:4px 10px}
.phead .r .seg{margin-left:auto}

.dashcards{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}
.dashcard{background:var(--panel);border:1px solid var(--line);border-radius:8px;
  padding:16px 18px}
.dcname{font-family:"IBM Plex Mono",monospace;font-size:10px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint)}
.dcbig{font-family:Fraunces,Georgia,serif;font-size:26px;font-weight:600;
  line-height:1.15;margin-top:5px;font-variant-numeric:tabular-nums}
.dcsub{font-size:12px;color:var(--dim);margin-top:3px}
.dcsub b{color:var(--ink);font-weight:600}
.dcbar{height:8px;border-radius:4px;background:var(--sunk);
  border:1px solid var(--line);margin:12px 0 8px;overflow:hidden}
.dcbar i{display:block;height:100%;background:var(--berry);border-radius:4px}
.dcfoot{display:flex;align-items:center;font-size:12px}
.dcpct{font-weight:600}
.dcpct.up{color:var(--ok)} .dcpct.down{color:var(--dim)}
.dcbills{color:var(--faint);font-size:11px}

/* -------------------------------------------------------- the trend strip -- */
/* Two columns, so the shops are compared by eye rather than by scrolling from
   one to the other and remembering. One below the narrow breakpoint. */
.trendcols{display:grid;grid-template-columns:1fr 1fr;gap:20px}
@media(max-width:820px){.trendcols{grid-template-columns:1fr;gap:16px}}
.trendcol{min-width:0}
.trendname{font-family:"IBM Plex Mono",monospace;font-size:10px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint);margin:4px 0 6px}
.trendwrap{padding-bottom:2px}
svg.trend{display:block;width:100%;height:auto}
/* The track is the frame, the fill is the fact. One hue for every bar on the
   board: which outlet you are looking at is said in words above it, so colour
   is left free to mean nothing at all — which is the safest thing it can mean. */
svg.trend .trackbar{fill:var(--sunk);stroke:var(--line);stroke-width:1}
svg.trend .soldbar{fill:var(--berry)}
/* Dashed, and over the bar rather than under it: it is a threshold, not another
   quantity, and it has to stay visible where the bar has passed it. */
svg.trend .tgtline{stroke:var(--ink);stroke-width:1.5;stroke-dasharray:3 2;opacity:.72}
svg.trend .trendlab{fill:var(--faint);font-family:"IBM Plex Mono",monospace;
  font-size:9px;letter-spacing:.06em}
/* The month's takings, turned to read upwards inside its own bar. Two colours,
   because the same figure sits on the berry fill when the bar is tall enough to
   hold it and on the panel when it is not — one colour would be invisible in
   one of the two places. */
svg.trend .barfig{font-family:"IBM Plex Mono",monospace;font-size:9px;
  font-weight:600;letter-spacing:.02em}
/* Not #fff. In dark mode the berry fill is a LIGHT pink and white on it is
   unreadable — the classic artifact bug, a colour that only works in the
   theme it was written in. The token flips with the fill it sits on. */
svg.trend .barfig.in{fill:var(--on-berry)}
svg.trend .barfig.out{fill:var(--dim)}
.dashkey{margin-top:10px}

/* ------------------------------------------------------- the two half-panels */
.dashcols{display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:12px}
.board.dashtab{min-width:0}
.board.dashtab tbody td{height:auto;padding:6px 8px;vertical-align:middle}
.board.dashtab td.wrap{position:relative;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
/* The rank bar lives BEHIND the name, not in a column of its own — twelve rows
   of ranked money read as a shape, and the shape costs no width in a panel that
   only has half a screen to give. */
.rankbar{position:absolute;left:0;top:3px;bottom:3px;border-radius:4px;
  background:var(--accent-soft);z-index:0;pointer-events:none}
.board.dashtab td.wrap > *:not(.rankbar){position:relative;z-index:1}
.board.dashtab td.wrap .sub{color:var(--faint);font-size:11px;margin-left:8px}

/* ==================================================== the customer import ====
   The paste box is deliberately large. Somebody is about to drop three hundred
   lines into it and they should be able to see that it landed. */
.importbox{width:100%;font-family:"IBM Plex Mono",monospace;font-size:12px;
  line-height:1.55;padding:12px 12px;border:1px solid var(--line2);
  border-radius:8px;background:var(--panel);color:var(--ink);margin-top:10px;
  resize:vertical;min-height:150px}
.importbox::placeholder{color:var(--faint)}

/* The counts, before anything is written. Big, because they are the whole point
   of the screen — the moment somebody stops reading them is the moment an
   import goes wrong quietly. */
.impstats{display:grid;grid-template-columns:repeat(auto-fit,minmax(122px,1fr));
  gap:8px;margin:14px 0 10px}
.impstat{background:var(--sunk);border:1px solid var(--line);border-radius:8px;
  padding:10px 12px;display:flex;flex-direction:column;gap:0px}
.impstat b{font-family:Fraunces,Georgia,serif;font-size:26px;font-weight:600;
  line-height:1.1;font-variant-numeric:tabular-nums}
.impstat span{font-size:11px;color:var(--faint);line-height:1.35}
.impstat.good b{color:var(--ok)}
.impstat.warn b{color:var(--warn)}
.impstat.bad  b{color:var(--crit)}
.board.cat td.mono{font-family:"IBM Plex Mono",monospace;font-size:12px}

/* The list itself. The number is the identity, so it is the one thing on the
   row set in the mono face — a column of numbers you can scan down without
   your eye slipping a digit. */
.board.cat td.mono.dim{color:var(--faint)}

/* THE LOCK. A saved number opens read-only and LOOKS it — struck through with
   the page's sunk tone rather than the panel's, so the difference is visible
   before anybody clicks into it and finds out. */
input.locked{background:var(--sunk);color:var(--dim);cursor:default;
  border-style:dashed}
button.small{font-size:11px;padding:4px 8px}
button.ghost.danger{color:var(--crit)}
button.ghost.danger:hover{background:var(--crit);color:#FFF;border-color:var(--crit)}

/* Pasting a list is the rarer job of the two — it happens once when the shop
   moves in and hardly ever again — so it folds away under the list it feeds. */
.importwrap{margin-top:22px;border-top:1px solid var(--line);padding-top:6px}
.importwrap>summary{cursor:pointer;font-size:12px;color:var(--dim);
  padding:8px 2px;list-style:none;user-select:none}
.importwrap>summary::-webkit-details-marker{display:none}
.importwrap>summary::before{content:"▸ ";color:var(--faint)}
.importwrap[open]>summary::before{content:"▾ "}
.importwrap>summary:hover{color:var(--ink)}

/* A tile you can open. It has to look pressable before anybody thinks to try —
   the whole point is that a figure is no longer something you take on faith. */
button.impstat{text-align:left;font:inherit;cursor:default;width:100%;
  border-radius:8px;transition:border-color .12s,background .12s}
button.impstat.can{cursor:pointer}
button.impstat.can:hover{border-color:var(--line2);background:var(--panel)}
button.impstat.can::after{content:"see the rows";font-size:10px;color:var(--faint);
  letter-spacing:.03em;margin-top:3px}
button.impstat.can:hover::after{color:var(--dim)}
button.impstat.on{border-color:var(--brandred);background:var(--panel)}
button.impstat.on::after{content:"hide the rows"}
button.impstat:disabled{opacity:1}

/* The address on a customer row: enough to recognise them by, never enough to
   push the money off the screen. The whole of it is on the cell's title. */
.board.cat td.addr{max-width:280px}

/* The customer's details, opened from the order screen. Sunk into the panel it
   belongs to, so it reads as part of the customer block rather than a second
   form floating in the middle of taking an order. */
.custdet{background:var(--sunk);border:1px solid var(--line2);border-radius:8px;
  padding:12px 12px 10px;margin-top:10px;display:flex;flex-direction:column;gap:8px}
.custdet .colrow{margin:0}
/* A firm action that is not THE action on the screen: outlined rather than
   filled, so it never competes with Save changes for the counter's eye. */
button.solid{border-color:var(--ink);color:var(--ink)}
button.solid:hover{background:var(--ink);color:var(--panel)}
button.solid:disabled{opacity:.45;cursor:not-allowed;border-color:var(--line2)}

/* ======================================================= the bill, over here */
/* THE SHOP'S WORDS: "if we want to edit from anywhere ... can we have a big pop
   up screen where we can edit the data rather than taking it to the order form
   template?"
   Clicking a bill used to navigate away: the board you were reading vanished —
   its day, its outlet, its search, the row your eye was on — and after saving
   you were handed a board that had to rebuild itself and find its place again.
   The panel goes over the top instead, and the board underneath does not move. */
/* A panel opened from inside a panel sits ABOVE it, and hands it back when it
   closes. Three backdrops at full strength would black the shop out, so the
   upper layers only barely darken what is under them. */
.sheet-back.stacked{background:rgba(20,10,8,.28)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .sheet-back.stacked{
  background:rgba(0,0,0,.4)}}
:root[data-theme="dark"] .sheet-back.stacked{background:rgba(0,0,0,.4)}
.sheet-back{position:fixed;inset:0;z-index:400;background:rgba(20,10,8,.55);
  display:flex;align-items:center;justify-content:center;padding:2vh 2vw}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .sheet-back{
  background:rgba(0,0,0,.7)}}
:root[data-theme="dark"] .sheet-back{background:rgba(0,0,0,.7)}

/* Three quarters of the screen, as asked for, with the rounded edge. */
.sheet{width:78vw;max-width:1500px;height:92vh;display:flex;flex-direction:column;
  background:var(--ground);color:var(--ink);border-radius:8px;overflow:hidden;
  box-shadow:0 30px 90px -20px rgba(0,0,0,.55);border:1px solid var(--line2)}
@media (max-width:1100px){.sheet{width:96vw;height:96vh}}

.sheet-head{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:10px 14px;border-bottom:1px solid var(--line);background:var(--panel)}
.sheet-name{display:flex;align-items:baseline;gap:10px;min-width:0;flex:0 1 auto}
.sheet-name b{font-family:"IBM Plex Mono",monospace;font-size:14px;white-space:nowrap}
.sheet-name .sub{color:var(--dim);font-size:12px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
/* The things you do to a WHOLE BILL live up here beside its number, not at the
   bottom of a form about its cakes. */
.sheet-acts{display:flex;gap:6px;flex-wrap:wrap;margin-left:auto}
.sheet-acts button{font-size:12px;padding:4px 10px;white-space:nowrap}
.sheet-acts button.danger{color:var(--crit);border-color:var(--crit)}
.sheet-acts button.danger:hover{background:var(--crit);color:#FFF}
.sheet-x{flex:0 0 auto;font-size:15px;line-height:1;padding:4px 10px}
.sheet-body{flex:1 1 auto;overflow:auto;padding:0 14px 16px;
  scrollbar-gutter:stable}

/* ------------------------------------------------- five things, right button */
.rowmenu{position:fixed;z-index:500;min-width:196px;background:var(--panel);
  border:1px solid var(--line2);border-radius:8px;padding:4px;
  box-shadow:var(--shadow);display:flex;flex-direction:column}
.rowmenu a{display:block;padding:6px 10px;border-radius:4px;font-size:13px;
  color:var(--ink);text-decoration:none;white-space:nowrap}
.rowmenu a:hover{background:var(--accent-soft);color:var(--accent)}
.rowmenu a.danger{color:var(--crit)}
.rowmenu a.danger:hover{background:var(--crit);color:#FFF}
.rowmenu-rule{height:1px;background:var(--line);margin:4px 6px}

/* ============================================================== the money bar */
/* THE SHOP ASKED FOR IT: "I want a static footer at the bottom of the page —
   with options for payment in, payment out and more other options to add."
   Taking a payment is not somewhere you GO. It happens in the middle of
   whatever you were already doing, at a counter with somebody standing at it —
   so it lives on a bar that is always there and opens over the top. */
/* ------------------------------------------------------------------- Add --
   The money bar is gone. It was a strip of furniture across the foot of every
   screen — costing 48px of an 1366x768 counter monitor for two buttons — and
   it lay on top of the message layer, so every error BCH360 raised on a money
   screen appeared underneath it. Both problems end with it.
   The two things it held are one tab in the band now, beside the screens they
   belong with, and they still open OVER whatever you were doing rather than
   navigating away from it. */
.addtab{display:inline-flex;align-items:center;gap:4px}
.addtab .caret{font-style:normal;font-size:9px;opacity:.8}
.addtab[data-open="1"]{background:rgba(255,255,255,.18)}
.addmenu{position:fixed;z-index:500;min-width:180px;
  background:var(--panel);border:1px solid var(--line2);border-radius:8px;
  box-shadow:var(--shadow);padding:4px;display:flex;flex-direction:column}
.addmenu a{display:block;padding:8px 12px;border-radius:4px;font-size:13px;
  color:var(--ink);text-decoration:none;cursor:pointer}
.addmenu a:hover,.addmenu a:focus-visible{background:var(--sunk);outline:none}

/* ------------------------------------------------ what the payment settles */
.paypanel{display:grid;grid-template-columns:minmax(0,340px) minmax(0,1fr);
  gap:14px;align-items:start;margin-top:14px}
.paypanel.one{grid-template-columns:minmax(0,520px);justify-content:center}
/* Payment in has a TABLE in it — a row a bill, ten columns wide — so it takes
   the whole width of the box rather than a 520px column with the columns
   falling off the right-hand edge. */
.paypanel.wide{grid-template-columns:minmax(0,1fr);margin-top:0}
/* Who it is from, what it came in as, and the note all read across one band at
   the top, so the bills below get the rest of the box. */
.paypanel.wide .colrow{align-items:flex-start;gap:12px;row-gap:10px}
@media (max-width:900px){.paypanel{grid-template-columns:1fr}}
.paypanel label{display:block;font-family:"IBM Plex Mono",monospace;font-size:9px;
  letter-spacing:.12em;text-transform:uppercase;color:var(--faint);margin-bottom:4px}
.paypanel input[type=date],.paypanel input[type=search],.paypanel input[type=text]{width:100%}

.owelist{display:flex;flex-direction:column;gap:4px;max-height:46vh;overflow:auto}
/* One bill a line, and it says what this money does to it before anything is
   saved: how much of it goes here, and what is still short afterwards. */
.owe{display:flex;align-items:center;gap:10px;margin:0;padding:6px 8px;
  border:1px solid var(--line);border-radius:6px;background:var(--panel);
  cursor:pointer}
.owe:hover{border-color:var(--accent)}
.owe.hit{border-color:var(--ok);background:var(--ok-soft)}
.owe.off{opacity:.5}
.owe input[type=checkbox]{width:17px;height:17px;flex:0 0 auto;margin:0;
  accent-color:var(--accent);cursor:pointer}
.owe-what{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:0px}
.owe-what b{font-size:12px}
.owe-what .sub{font-size:11px;color:var(--dim);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.owe-due{flex:0 0 auto;text-align:right;display:flex;flex-direction:column;gap:0px}
.owe-due b{font-size:13px}
.owe-due .sub{font-size:10px;color:var(--dim)}
.owe-due .sub.ok{color:var(--ok)}
.owesum{display:flex;flex-direction:column}

/* Money of a customer's that is already in our drawer, said on the order screen
   the moment his number is typed — otherwise it sits in the ledger being right
   and nobody ever knows it is there. */
.heldbit{border:1px solid var(--berry);border-radius:6px;padding:8px 10px;
  background:color-mix(in srgb, var(--berry) 8%, var(--panel))}
.heldbit label{display:flex;align-items:flex-start;gap:8px;margin:0;cursor:pointer;
  font-size:12px;color:var(--ink)}
.heldbit input[type=checkbox]{width:17px;height:17px;margin:1px 0 0;flex:0 0 auto;
  accent-color:var(--berry);cursor:pointer}
.heldbit b{color:var(--berry)}
.heldbit i{display:block;font-style:normal;color:var(--dim);font-size:11px;margin-top:1px}

/* One note across the counter, settling several bills. The pill says so on
   every row it produced, so a cash book can be read back to the note. */
.pill.in{background:var(--accent-soft);color:var(--accent);border:1px solid var(--line2)}
.pill.berry{background:var(--berry);color:var(--on-berry)}
.board.report td .sub .pill{margin-right:4px}

/* A payment is a FORM, not a screen. Half the width, in the middle, and only as
   tall as it needs to be — a small box you read at a glance beats a wide one
   you have to sweep across. */
.sheet.half{width:62vw;max-width:1120px;height:auto;max-height:78vh}
@media (max-width:1100px){.sheet.half{width:95vw;max-height:90vh}}

/* Half of half. A box with three fields in it does not want two thirds of a
   shop monitor — it wants to be the size of the thing it is asking for. */
.sheet.small{width:31vw;max-width:560px;min-width:380px;
  height:auto;max-height:80vh}
/* And a line of piping is one line. A box the size of a paragraph invites one. */
.sheet.tiny{width:26vw;max-width:460px;min-width:340px;height:auto}
/* On the narrow boxes the heading stays ONE line: a long subtitle was wrapping
   and pushing the close cross onto a row of its own, which read as a second
   heading and cost a row of height on a box built to be short. */
.sheet.small .sheet-head,
.sheet.tiny .sheet-head{flex-wrap:nowrap}
.sheet.small .sheet-name,
.sheet.tiny .sheet-name{min-width:0;flex:1 1 auto}
.sheet.tiny .msgedit input{font-family:Fraunces,Georgia,serif;font-size:17px;
  width:100%;padding:8px 10px}
@media (max-width:1100px){
  .sheet.small,.sheet.tiny{width:94vw;min-width:0}
}

/* The list of his bills is the one part that can run long — twenty unpaid bills
   must not push the Save button off the bottom of the screen. The list takes
   whatever room is left over and scrolls inside itself; the figures and the
   button below it are always on the screen. */
.sheet.half .sheet-body{display:flex;flex-direction:column;min-height:0}
.paypanel.wide,
.paypanel.wide>.panel.grow,
.paypanel.wide>.panel.grow>.pbody{display:flex;flex-direction:column;
  align-items:stretch;min-height:0;min-width:0;flex:0 1 auto}
.paypanel.wide>.panel.grow{flex:1 1 auto}
.paypanel.wide>.panel.grow>.pbody{flex:1 1 auto}
.owescroll{flex:1 1 auto;min-height:96px;overflow:auto;scrollbar-gutter:stable}
.owescroll thead th{position:sticky;top:0;z-index:2;background:var(--panel)}

/* Pick the mode, type the figure, press ＋ Payment for a second one. */
.paylines{display:flex;flex-direction:column;gap:6px}
.payline{display:grid;grid-template-columns:1fr 118px 28px;gap:8px;align-items:center}
.payline select{min-width:0;padding:6px 6px;font-size:12px}
.payline input{text-align:right;padding:6px 8px}
.payline .x{padding:2px 6px;font-size:14px;line-height:1;color:var(--faint);text-align:center}
.payline .x:hover{color:var(--crit)}
.addpay{margin-top:6px;font-size:12px;padding:4px 10px}
/* The number the receipt is about to get. */
.recno{font-size:13px;font-weight:600;color:var(--accent);padding:6px 0}

/* One invoice a line, as asked for: date, number, where, the cake, and the
   figure going on it — which can be argued with, because a part-paid bill is a
   decision and not arithmetic. */
/* Ten columns in a box you can read at a glance: the widths are set rather than
   guessed, so the AMOUNT box — the one thing on this table you TYPE in — is
   never the column that falls off the right-hand edge. */
.owetable.board.report{width:100%;min-width:0;table-layout:fixed}
.owetable td,.owetable th{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  padding-left:6px;padding-right:6px}
.owetable th:nth-child(1),.owetable td:nth-child(1){width:30px;padding-left:8px}
.owetable th:nth-child(2),.owetable td:nth-child(2){width:100px}
.owetable th:nth-child(3),.owetable td:nth-child(3){width:146px}
.owetable th:nth-child(4),.owetable td:nth-child(4){width:82px}
.owetable th:nth-child(6),.owetable td:nth-child(6){width:56px}
.owetable th:nth-child(7),.owetable td:nth-child(7){width:34px}
.owetable th:nth-child(8),.owetable td:nth-child(8){width:90px}
.owetable th:nth-child(9),.owetable td:nth-child(9){width:68px}
.owetable th:nth-child(10),.owetable td:nth-child(10){width:98px;padding-right:8px}
.owetable tbody tr.off{opacity:.45}
.owetable tbody tr.hit td{background:var(--ok-soft)}
.owetable input[type=checkbox]{width:16px;height:16px;margin:0;accent-color:var(--accent);
  cursor:pointer}
.owetable input.alloc{width:100%;text-align:right;padding:4px 6px}
.owetable td.wrap{overflow:hidden;text-overflow:ellipsis}
.owetable .sub{color:var(--faint);font-size:11px;margin-left:5px}
/* The receipt read back: the bills it settled, flat, nothing to tick. */
.owe.flat{cursor:default}
.owe.flat:hover{border-color:var(--ok)}

/* A payment that came in on a receipt is one leg of a document. The pill says
   so, carries the number, and opens the receipt — which is the only place it
   can be undone, whole. */
.pill.link{background:var(--accent-soft);color:var(--accent);border:1px solid var(--line2);
  text-decoration:none;cursor:pointer;margin-left:6px;display:inline-flex;
  align-items:center;gap:4px}
.pill.link:hover{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.pill.link .no{font-family:"IBM Plex Mono",monospace;font-size:9px;opacity:.85;
  letter-spacing:0;text-transform:none}

/* THE BILL IS SAVED, THE MONEY IS NOT. See sayNotTaken() in neworder.js: the
   one message in BCH360 that does not fade and does not close on a stray click,
   because what it is reporting is a bill on the day board with nothing paid on
   it. Sized and coloured to be read, not dismissed. */
.askcard[role="alertdialog"]{max-width:420px}
.askcard[role="alertdialog"] h2{color:var(--crit)}
.askcard[role="alertdialog"] p{margin:8px 0;line-height:1.45}
.askcard .notpaid-ref b{font-size:15px}
.askcard .notpaid-why{color:var(--dim);font-size:13px;
  border-left:3px solid var(--line);padding-left:8px}
.askcard .notpaid-do{font-weight:600}

/* A till on a payment line that is not this counter's — put there by a receipt
   taken at the other shop. Shown, not hidden: the select has to say what the
   line holds. See moneyLines() in money.js. */
.payline select option.notmine{color:var(--crit)}

/* The line under the heading on the cancel question: the heading states the
   figure, this asks the question about it. See askAboutMoney() in neworder.js. */
.askcard .asksub{margin:-4px 0 10px;color:var(--dim);font-size:13px}

/* =========================================================== the month grid ==
   The office's own sheet: one row per day, three columns per account. See
   renderMonth() in dayend.js for why the office reads a month where a counter
   closes a day. */
/* THE MONTH SCROLLS INSIDE ITS OWN PANEL, and this is the reason: sticky
   positions against the nearest scrolling ancestor, and .monthscroll is one the
   moment it has overflow on either axis. With no height of its own it never
   scrolled, so the heading row and the date column sat still relative to a box
   that was itself sliding up the page — and thirty-one rows of figures arrived
   with no column headings over them, on the one screen that cannot be read
   without them.
   Giving it a height puts the scroll where the headings expect it. It is also
   what the shop asked for: the page does not scroll, the thing inside it does. */
.monthscroll{max-height:calc(100vh - 208px);overflow:auto}
table.monthgrid{font-size:12px;border-collapse:separate;border-spacing:0;
  table-layout:fixed;width:auto;min-width:100%}
table.monthgrid th,table.monthgrid td{padding:3px 6px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
/* The account name over its own three columns, ruled off from the next so the
   eye does not wander a column left while reading down a month. */
table.monthgrid thead th.grp{
  text-align:center;font-weight:600;border-left:2px solid var(--line2);
  background:var(--sunk);letter-spacing:0}
table.monthgrid thead th.grp.ours{background:var(--accent-soft)}
table.monthgrid thead th{position:sticky;top:0;z-index:2;background:var(--panel)}
table.monthgrid thead tr:nth-child(2) th{top:25px;font-size:10px;
  letter-spacing:0;color:var(--faint);text-transform:none;font-weight:600;
  padding-left:3px;padding-right:6px}
/* The date column stays put while the month scrolls sideways: thirty-one rows
   of figures with no date against them is not a sheet anybody can read. */
table.monthgrid .daycol{position:sticky;left:0;z-index:3;background:var(--panel);
  border-right:1px solid var(--line2);font-size:11px;text-align:left}
table.monthgrid thead .daycol{z-index:4}
table.monthgrid tbody tr:hover td{background:var(--row)}
table.monthgrid tbody tr:hover .daycol{background:var(--row)}
table.monthgrid tr.istoday td{background:var(--accent-soft)}
table.monthgrid tr.istoday .daycol{background:var(--accent-soft);font-weight:700}
table.monthgrid td.dim{color:var(--faint)}
table.monthgrid td.ahead{background:var(--sunk)}
/* Level is a quiet dot; ANY gap is loud, in either direction. The sign is not a
   judgement here — a surplus usually means a sale that never got recorded. */
table.monthgrid .lvl{color:var(--faint)}
table.monthgrid td.gap b{color:var(--crit)}
table.monthgrid input.mcell{width:100%;padding:0px 4px;font-size:12px;
  text-align:right;background:var(--panel)}
table.monthgrid .signcol{position:sticky;right:0;background:var(--panel);
  border-left:1px solid var(--line2);text-align:center}
table.monthgrid tbody tr:hover .signcol{background:var(--row)}
table.monthgrid .signbtn{padding:0px 8px;font-size:11px;white-space:nowrap}
table.monthgrid .signcol .pill{font-size:10px}

/* The reason, asked once for the row. */
.whycard{max-width:460px}
.whyrow{margin:10px 0}
.whyhead{display:flex;justify-content:space-between;align-items:baseline;
  gap:12px;margin-bottom:3px;font-size:13px}
.whyhead .over{color:var(--warn);font-weight:600}
.whyhead .short{color:var(--crit);font-weight:600}
.whyrow input{width:100%}
.whyfoot{display:flex;gap:8px;justify-content:flex-end;margin-top:14px}

/* The sign-off cell carries two things for the owner: the day's own button, and
   the way back. See openBack() in dayend.js — a signed day is sealed against
   every correction there is, so the login that can unseal it has to be able to
   reach that from the screen the day lives on. */
.signwrap{display:inline-flex;align-items:center;gap:4px}
table.monthgrid .undobtn{padding:0 6px;font-size:13px;line-height:1.5;
  color:var(--dim)}
table.monthgrid .undobtn:hover{color:var(--accent)}
.backcard{max-width:520px}
.backrow{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:8px 0;border-top:1px solid var(--line)}
.backrow .sub{display:block;font-size:12px;color:var(--dim);margin-top:2px}
.backrow button{white-space:nowrap}

/* ================================================================ payroll ===
   The one table in BCH360 where cells are typed INTO the report. Everything
   about it says which those are: the six shaded ones and no others. */
/* ONE WIDTH FOR EVERY FIGURE COLUMN, asked for by the shop and right: fifteen
   columns of money and hours read as a grid when they are a grid, and as a
   jumble when each one is sized to its own longest number. table-layout:fixed
   divides whatever is left after the name column equally between them, so the
   widths cannot drift as the figures change from month to month.
   1500 is the floor: fifteen columns of ~85px, which is what DEDUCTIONS needs
   at 9px mono with its letter-spacing. */
.board.pay{table-layout:fixed;min-width:1500px}
.board.pay thead th:first-child,
.board.pay td.nm,
.board.pay tfoot td:first-child{width:230px;white-space:nowrap}
/* Headings CENTRED over their columns, not hard against the right. A heading
   is a label for the column, not another figure in it — and .tr on the th is
   what was pinning them right, so this has to out-specify it. */
.board.pay thead th{white-space:nowrap;text-align:center}
.board.pay thead th.tr{text-align:center}
.board.pay thead th:first-child{text-align:left}
.board.pay td.nm{font-weight:600}
.board.pay .sub{display:block;font-size:10px;color:var(--faint);font-weight:400}
/* Three groups, the way the shop's own sheet reads: what he earned, what came
   off, what he takes home. A border and not a colour — the sheet uses colour
   and colour is the first thing that stops printing. */
.board.pay .grp{border-left:2px solid var(--line2)}
/* A gold wash, not a grey one: grey reads as disabled and these are the live
   cells. This is the whole argument of the screen in one declaration. */
.board.pay td.typed{background:var(--typed);box-shadow:inset 0 0 0 1px var(--typed-edge)}
.board.pay td.typed input{width:100%;text-align:right;border:0;background:transparent;
  padding:2px 4px;font-size:12px}
.board.pay td.typed input:focus{outline:2px solid var(--accent);outline-offset:-2px}
.board.pay td.adv{cursor:pointer}
.board.pay td.adv.has:hover{background:var(--accent-soft);color:var(--accent)}
/* Not an error — a question. Somebody has entered a day over thirty AND extra
   hours, which is usually the same work twice and sometimes is not. */
.board.pay td.ask{color:var(--warn)}
.board.pay td.ask .sub{color:var(--warn)}
.board.pay tfoot td{border-top:2px solid var(--line2);font-weight:700;
  background:var(--panel);position:sticky;bottom:0}
.lockbar{display:flex;align-items:center;gap:10px;font-size:12px;
  color:var(--dim);padding:8px 2px 0;flex-wrap:wrap}
.lockbar .pill{margin:0}

/* A form in a panel: label above the box, the way a person reads a form. */
.fld{display:flex;flex-direction:column;gap:4px;margin-bottom:14px}
.fld > label{font-family:"IBM Plex Mono",monospace;font-size:9px;
  letter-spacing:.13em;text-transform:uppercase;color:var(--faint)}
.fld .hint{margin:2px 0 0}
.pf{display:flex;gap:10px;justify-content:flex-end;margin-top:18px;
  padding-top:14px;border-top:1px solid var(--line)}

/* Whose birthday it is, over the day board. Quiet: it is a kindness, not an
   alert, and it must never look like something has gone wrong. */
.bday{display:flex;align-items:center;gap:10px;margin:12px 0 0;
  padding:9px 14px;border-radius:6px;font-size:14px;
  background:var(--accent-soft);border:1px solid var(--line2);color:var(--ink)}
.bday .cake{font-size:16px;line-height:1}

/* ------------------------------------------------------------- the payslip --
   One per person, printed on A4 rather than the thermal roll: a payslip is a
   document somebody keeps, and the bill's @page is 80mm for the whole file. */
.slips{display:none}
.slip{page-break-after:always;break-after:page;padding:18mm 16mm;
  font-family:Inter,system-ui,sans-serif;color:#000}
.slip h1{font-family:Fraunces,Georgia,serif;font-size:22pt;margin:0 0 2mm}
.slip .who{font-size:12pt;font-weight:600;margin:0}
.slip .mon{font-family:"IBM Plex Mono",monospace;font-size:9pt;
  letter-spacing:.14em;text-transform:uppercase;color:#666;margin:1mm 0 8mm}
.slip .tl{font-size:11pt;padding:2mm 0;border-bottom:1px solid #EEE}
.slip .tl.sum{border-bottom:0;border-top:1.5px solid #000;font-weight:700;
  margin-top:2mm;padding-top:3mm}

@media print{
  html.printing-a4 #printarea.slips{display:block}
  html.printing-a4 .slip{padding:14mm 12mm}
}


/* --------------------------------------------------------------------------
   Cakes and Desserts, on the shelf's "Came in" list. Two piles come off the
   van and two piles get booked in, so the list says which is which rather
   than leaving the person to sort it in their head.
   -------------------------------------------------------------------------- */
.kindhead{display:flex;align-items:baseline;gap:10px;margin:12px 0 2px;
  font-family:"IBM Plex Mono",monospace;font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint)}
.kindhead .r{margin-left:auto;letter-spacing:0;text-transform:none}
.kindhead:first-of-type{margin-top:10px}
/* The same two words down the night count. A row rather than a heading over
   its own table, so the five figure columns stay in one grid — Counted under
   the cakes has to line up with Counted under the desserts or the column
   cannot be read down. */
.board.shelf tr.kindrow td{background:var(--sunk);border-top:1px solid var(--line2);
  font-family:"IBM Plex Mono",monospace;font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint);padding-top:9px;padding-bottom:5px}
.board.shelf tbody:first-of-type tr.kindrow td{border-top:none}

/* The two payslip buttons on a payroll row. They appear only on a CLOSED
   month — a half-typed payslip on somebody's phone is an argument about a
   figure that was never final. */
.slipbtns{display:inline-flex;gap:6px;margin-left:10px;vertical-align:middle}
.slipbtns .tiny{font-size:10.5px;padding:2px 8px;line-height:1.5}
.slipbtns .sub{font-size:10.5px}

/* A payroll line whose pay no longer matches the staff record. Shown, never
   applied by itself: a rise in September has no business reaching back into
   July, but a salary typed wrong used to be permanent. */
.board.pay td.paydiff .tiny{display:block;width:100%;margin-top:3px;
  font-size:10px;padding:1px 4px;line-height:1.4;text-align:right;
  border-color:var(--gold-deep);color:var(--gold-deep);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.board.pay td.paydiff .tiny:hover{background:var(--accent-soft)}
