/* Whirl Order -- the GM-facing order screen.
   Tablet first: big numbers, big targets, one column, no horizontal scroll. */

#oBody { padding: 0 0 190px; }

/* ---------------------------------------------------------------- summary */
.summary {
  padding: 14px 16px;
  background: #f4f7f4;
  border-bottom: 1px solid #dfe6df;
  font-size: 15px;
  line-height: 1.5;
}
.summary strong { font-size: 20px; }
.summary .muted { color: #667; }

/* The count prompt -- only when something needs eyes on it. */
.checkbar {
  margin: 12px 16px;
  padding: 12px 14px;
  border-radius: 10px;
  background: #fff8e6;
  border: 1px solid #e8d089;
  font-size: 15px;
}
.checkbar b { display: block; margin-bottom: 3px; }

/* ------------------------------------------------------------------ list */
.olist { padding: 4px 10px 0; }

/* `.orow` is a TABLE ROW as of 2026-08-27. It used to be a flex card -- name and figures
   stacked on the left, stepper pushed right -- and that `display: flex` survived the rewrite,
   which collapsed every row into a huddle at the left edge while the headings stayed spread
   across the full width. Table rows take their widths from the columns; nothing here may set
   display, flex or gap. */
.orow { border-bottom: 1px solid #eceeec; }
/* The row-level fade lives ONE place only, further down, and deliberately spares the item cell so
   the over-recipe note is not dimmed with it. There was a second copy here (2026-08-29); changing
   the other one alone did nothing, because this one still faded the whole row. Two rules for one
   decision is how a fix passes its own test and fails on screen. */
.orow.check { background: #fffbf0; }

.oinfo { flex: 1 1 auto; min-width: 0; }
.oname {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.osub {
  margin-top: 3px;
  font-size: 13px;
  color: #5a635a;
  line-height: 1.45;
}
.osub .sep { color: #b8c0b8; padding: 0 5px; }
.osub .warn { color: #a8710c; font-weight: 600; }
.osub .bad  { color: #b3261e; font-weight: 600; }

.otag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
  background: #e7edf7; color: #24437e;
}
.otag.flag { background: #fdecc8; color: #7a5300; }
/* Added only to reach a supplier's minimum -- deliberately NOT the amber of a thing needing
   attention. It is information about where a number came from, not a warning. (2026-08-29) */
.otag.top  { background: #e7eef9; color: #1f3f6b; }

/* "Done with PFG" / "Undo top-up", beside that supplier's own total. */
.dtopbtn { margin-left: 10px; font-size: 13px; padding: 6px 12px; }
.dtopup  { margin-left: 10px; font-size: 13px; color: #6b746e; white-space: nowrap; }

/* stepper */
.ostep { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.ostep button {
  width: 42px; height: 42px;
  border-radius: 10px;
  border: 1px solid #cfd6cf;
  background: #fff;
  font-size: 22px; line-height: 1;
  color: #24422c;
}
.ostep button:active { background: #eef3ee; }
.ostep input {
  width: 60px; height: 44px;
  text-align: center;
  font-size: 21px; font-weight: 700;
  border: 1px solid #cfd6cf; border-radius: 10px;
  background: #fff;
}
.ostep input.edited { border-color: #1f7a3d; background: #f2fbf5; }

/* --------------------------------------------------------------- bottom */
.bar {
  position: fixed; left: 0; right: 0; bottom: 0;
  background: #fff;
  border-top: 1px solid #d8ded8;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  box-shadow: 0 -4px 14px rgba(0,0,0,.07);
}
.baskets { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 9px; }
.basket {
  flex: 1 1 auto;
  padding: 7px 10px;
  border-radius: 9px;
  background: #f3f6f3;
  border: 1px solid #e0e6e0;
  font-size: 13px;
  line-height: 1.35;
}
.basket b { display: block; font-size: 15px; }
.basket.under { background: #fff4f3; border-color: #f0c4bf; }
.basket .fee { color: #b3261e; font-weight: 600; }

/* EACH SUPPLIER IS PLACED FROM ITS OWN BASKET (2026-08-29). The single button under the row of
   baskets meant all of them at once; the action now sits with the quantity it acts on. Full width
   inside the card so it is a real target on a tablet, and the card keeps its own colour -- a
   supplier under its floor still reads as the one needing attention. */
.basket .bplace { width: 100%; margin-top: 8px; padding: 11px; font-size: 15px; }
/* After it has been placed there are TWO buttons -- change it, or add a second one -- because the
   screen asks which by what it offers rather than in a dialog. Side by side, so they read as one
   question with two answers. (2026-08-29) */
.basket.placed .bplace { width: calc(50% - 4px); display: inline-block; font-size: 14px; }
.basket.placed .bplace + .bplace { margin-left: 6px; }
/* Already placed today: the card recedes and the button stops being the thing you reach for, but
   it stays usable -- placing again after adding a line is normal, and the record keeps both. */
.basket.placed { background: #f1f5f2; border-color: #dbe3dd; color: #6b746e; }
.basket.placed b { color: #2f3a34; }
/* A supplier with nothing to order. Present, so four suppliers always read as four, but visibly
   not something to act on -- and no button, because there is nothing to place. (2026-08-29) */
.basket.quiet { background: #f6f8f6; border-color: #e6ebe7; color: #7a827a; }
.basket.quiet b { color: #55605a; }

/* ------------------------------------------------------------- blocked */
.blocked { margin: 20px 16px; padding: 18px; border-radius: 12px;
           background: #fff4f3; border: 1px solid #f0c4bf; }
.blocked h2 { margin: 0 0 8px; font-size: 20px; color: #8c1d18; }
.blocked ul { margin: 10px 0 10px 18px; }
.blocked li { margin: 4px 0; }
.blocked .muted { color: #667; font-size: 14px; }

.hidden { display: none !important; }

/* NO SPINNER ARROWS ON THE TWO TYPED BOXES (2026-08-29).
   `type="number"` gives the desktop browser a pair of up/down arrows inside the box. On the
   OVERRIDE box a single click on the down arrow of an empty field writes **0** -- which wins over
   both the system's figure and the GM's count, and so silently zeroes that item's order. On the
   COUNT box they are a stepper by another name, and the stepper was removed from this screen on
   purpose (Lar, 2026-08-27: "this allows them to just change the order without counting").
   The keyboard is unaffected: `inputmode` still asks for a numeric pad on a tablet.
   This does NOT explain the 0 found in store 680's override box -- how that got there is unknown
   -- it removes one way it could. */
.orow input[type="number"]::-webkit-outer-spin-button,
.orow input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.orow input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* ------------------------------------------------------------ the send step */
.sendpanel { padding: 18px 16px 60px; }
.sendpanel h2 { margin: 0 0 6px; font-size: 21px; }
.sendpanel .muted { color: #667; font-size: 14px; margin: 0 0 18px; line-height: 1.5; }
.sendrow {
  margin-bottom: 16px; padding: 14px;
  border: 1px solid #e0e6e0; border-radius: 12px; background: #fff;
}
.sendhd { font-size: 15px; margin-bottom: 10px; }
.sendhd b { font-size: 17px; }
.sendrow button.primary { width: 100%; padding: 14px; font-size: 16px; }
.showto { margin-top: 9px; font-size: 13px; color: #5a635a; line-height: 1.45; }
.swarn {
  margin: 0 0 10px; padding: 9px 11px; border-radius: 8px;
  background: #fff4f3; border: 1px solid #f0c4bf; color: #8c1d18; font-size: 13px;
}
#sendDone { width: 100%; margin-top: 8px; }

/* A supplier order that may not be sent -- PFG under its case floor. No button here on
   purpose: the floor is policy, so the screen must not offer a way around it. */
.sendrow.blocked-row { background: #fff8f7; border-color: #f0c4bf; }
.sblock {
  padding: 11px 12px; border-radius: 9px;
  background: #fff; border: 1px solid #f0c4bf; color: #8c1d18;
  font-size: 14px; line-height: 1.5;
}
.sblock b { font-size: 15px; }

/* The count unit shown beside a case figure -- "3 cases (90 Sheets)". Recessive: the
   case count is the order, the sheet count is only there to make it recognisable. */
.asunit { color: #7a827a; }

/* ---------------------------------------------------------------------------
   THE ORDER TABLE (2026-08-27)
   Replaces the old one-line-under-the-name layout. Lar: "its virtually impossible
   to read. You have all this white space and you shoved it below the name in tiny
   print." Numbers now line up under headings so a GM can read DOWN a column to
   compare items and ACROSS a row to see the arithmetic.
   --------------------------------------------------------------------------- */
/* A CAP, NOT FULL WIDTH. On a desktop monitor `width: 100%` stretched the six columns across
   2000px, so the item name and its figures ended up a hand's width apart and the eye had to
   travel to connect them. The table is read as a block: the item column takes what it needs and
   the figures sit right beside it. */
.otable { width: 100%; max-width: 1180px; border-collapse: collapse; }
.otable th, .otable td { padding: 8px 10px; white-space: nowrap; }
/* Widths and alignment are set ONCE, in the table block at the foot of this file. The generic
   `th:not(.oit)` width rule that used to live here gave `.rev` 108px while the frozen-column
   offsets assumed 106, drifting the whole pinned block by 2px. */

/* The group strip above the headings -- names the three questions the columns answer.
   Both header rows stick: the group strip at the very top, the column names directly under it.
   `top` on the second row must equal the first row's height (4+4 padding + ~15 line box). */
/* THE GROUP ROW LEADS (Lar, 2026-08-29: "how many to order can be bigger and darker"). It was
   11px at #6d7873 -- lighter and smaller than the column labels beneath it, so the two things that
   say what half of the table you are looking at were the faintest text on the screen. Now the
   larger, darker of the two header rows, which is the order a reader meets them in. `top` on the
   second row still has to equal this row's height; both are stated below. */
.otable tr.ogrp th {
  font-size: 13px; text-transform: uppercase; letter-spacing: .04em;
  color: #33413a; font-weight: 700; text-align: center;
  background: #f3f7f4; border-bottom: 1px solid #e2e8e4; padding: 6px 10px;
  position: sticky; top: 0; z-index: 4;
}
/* THE LABEL MUST NOT SET THE COLUMN WIDTH (Lar, 2026-08-28: "too much dead space here").
   `white-space: nowrap` on every th/td meant the widest thing in each figure column was its own
   HEADING, not its figures: "DELIVERED" is nine characters and "AVG DAILY USE" thirteen, against
   values of one or two digits. So every number sat at the far right of a column sized for a word.
   Wrapping is allowed HERE ONLY -- the figures themselves still never wrap, and the item name has
   its own rule below. The heading grows a second line instead of the table growing a column. */
/* `top` MUST equal the group row's rendered height, or the two sticky rows overlap as the list
   scrolls. Measured at 30.7px after the group row was enlarged on 2026-08-29 (13px text, 6px
   padding); 31px. Re-measure if that row's size or padding changes again. */
.otable tr.ohead th {
  text-transform: uppercase;
  color: #55605a; border-bottom: 2px solid #d9e1dc;
  position: sticky; top: 31px; background: #fff; z-index: 4;
  white-space: normal;
}
/* ...but not the four frozen ones: they are pinned to fixed offsets, so their width is already
   settled and a wrapped label there would only make the header taller for nothing. */
/* "ORDER THIS" and "OVERRIDE" WRAP TOO (Lar, 2026-08-29: "ORDER THIS can be on two lines and this
   column can be narrowed, so can override, and they should both be the same size"). They were held
   on one line because their width was fixed anyway -- but that width was set BY the label, and both
   cells hold at most three digits. Two short lines cost nothing and give the item name 44px. */
.otable tr.ohead th.oit { white-space: nowrap; }
.otable tr.ohead th.oit { white-space: normal; }
.otable th.oit, .otable td.oit { white-space: normal; min-width: 260px; }

.otable tbody tr { border-bottom: 1px solid #eef1ef; }
/* NOTHING TO ORDER HERE -- faded so the eye can skip it. But the fade must not swallow the
   over-recipe note (Lar, 2026-08-29: "you only made instacart bold"). It looked like the bold red
   had only been applied to some rows; in fact every row had it, and the ones ordering ZERO were
   dimmed to 55% on top of it. Avocado and bacon order nothing at 680, so their warning was faded
   while blueberries' was not.
   `opacity` cannot be undone by a child -- a child can never be more opaque than its parent -- so
   the fade is applied to the FIGURE cells only, and the item cell is muted with COLOUR instead.
   A colour is inherited, so `.odrift` simply overrides it and stays full-strength red.
   539 of the 1,564 faded rows fleet-wide carry a drift note; un-fading all of those would have
   dropped the fade on a third of the list and destroyed the point of it. */
.otable tbody tr.zero td:not(.oit) { opacity: .55; }
.otable tbody tr.zero .oname       { color: #8d968f; }
.otable tbody tr.zero .onotes .u,
.otable tbody tr.zero .onotes .ounit { color: #a7b0a9; }
.otable tbody tr.check { background: #fffbf0; }

/* ============================================================================
   THE WORKING, ONE TAP AWAY (Lar, 2026-08-28: "I think it is too busy ... the last count,
   received, amount you used, and recipe usage should be available through a more info button").
   Last count / Received / You used came off the row and became a sum underneath it, so the
   arithmetic behind "We think" is still checkable but is not charged to all 200 rows.
   A row we have flagged opens by itself -- see detailRow().
   ============================================================================ */
.odtog {
  margin-left: 8px; border: 1px solid #dbe3dd; background: #fff; color: #55605a;
  border-radius: 8px; min-width: 30px; min-height: 30px; line-height: 1;
  font-size: 16px; font-weight: 700; cursor: pointer; vertical-align: middle;
}
.odtog:hover { background: #f3f7f4; }
.otable tr.odet.hidden { display: none; }
.otable tr.odet > td {
  padding: 2px 10px 12px 10px; text-align: left; border-bottom: 1px solid #eef1ef;
  background: #fbfcfb;
}
.otable tr.check + tr.odet > td { background: #fffbf0; }
/* The sum reads as a sum: label above figure, in the order they are added. */
.odsum, .odmore { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 18px; }
.odmore { margin-top: 6px; }
.odsum .odk, .odmore .odk {
  font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: #6d7873;
}
.odsum .odv, .odmore .odv {
  font-size: 15px; font-variant-numeric: tabular-nums; color: #2f3a34; margin-right: 6px;
}
.odsum .odeq, .odmore .odeq { color: #2f3a34; }
.odsum .odtotal, .odmore .odtotal { font-weight: 700; }
/* The second line: the daily rate doing the one job it has -- producing what is needed by the
   second delivery -- and showing its working from the recipe rate up. A SENTENCE, not a labelled
   sum: here the words are part of the phrase, so they are set in normal case while the figures
   carry the weight. (Lar, 2026-08-29) */
.odneed {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 7px;
  margin-top: 8px; padding-top: 8px; border-top: 1px solid #e6ebe7;
}
.odneed .odv { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; color: #2f3a34; }
.odneed .odtotal { font-weight: 700; }
.odneed .odt { font-size: 13px; color: #55605a; }
.odneed .odx { font-size: 13px; color: #97a09a; font-weight: 700; padding: 0 4px; }
.odwinline { flex-basis: 100%; font-size: 11px; color: #97a09a; margin-top: 3px; }
.odmore .odv { color: #6b746e; }
/* The span each figure covers, under its label. Quiet -- it is a qualifier, not a value -- but
   present, because two figures over two different windows sitting side by side with nothing
   saying so is how a reader concludes the panel disagrees with itself. (2026-08-29) */
/* `.odneed` has no `.odwin` of its own: it is one phrase, so it carries ONE caption for the whole
   line (`.odwinline` above) rather than a qualifier under each figure. It was briefly listed here
   and its caption ran into the label -- "A DAYLAST 7 DAYS, INCL. THE 2.5x". (2026-08-29) */
.odsum .odwin, .odmore .odwin {
  display: block; font-style: normal; font-weight: 400; text-transform: none;
  letter-spacing: 0; font-size: 11px; color: #97a09a; margin-top: 1px;
}
/* A row re-anchored by a spot count says so beside its date -- otherwise a later date next to
   "Counted" reads as a typo rather than as the reason this row measures from a different day. */
.odspot {
  font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: #8a5a00; background: #fdf3e0; border-radius: 6px; padding: 1px 6px; margin-left: 4px;
}

/* Tabular figures so the digits align in a column -- the whole point of the change. */
.otable td.n { font-variant-numeric: tabular-nums; color: #2f3a34; }
.otable td.n.m { color: #b9c0bb; }              /* an em-dash, i.e. nothing happened */

.otable .oname { line-height: 1.3; }
.otable .onotes { color: #6b746e; margin-top: 2px; line-height: 1.5; }
.otable .onotes .u { color: #8a938e; }
/* The row's UNIT. Every figure on the row is in it, so it reads as a label rather than an aside:
   the item name's colour and weight, not the faint grey the other notes share. (2026-08-29) */
.onotes .ounit { color: #24422c; font-weight: 700; }
.otable .onotes .sep { color: #c3cac5; padding: 0 5px; }
.otable .onotes .warn { color: #a8710c; font-weight: 600; }
.otable .onotes .bad  { color: #b3261e; font-weight: 600; }
/* The gap against the VENDOR's own recipe -- bold red whichever way it runs (Lar, 2026-08-29).
   It used to be graded amber-then-red by size, which buried a 25% gap among the informational
   notes; a store off the franchisor's portion is the same kind of fact at any size. */
.otable .onotes .odrift { color: #b3261e; font-weight: 700; }

/* THE FIRST FOUR COLUMNS ARE FROZEN (Lar's decision, 2026-08-28).
   The table is ~1,006px and a portrait iPad is 768-834, with pinch disabled by the viewport --
   so 170-240px sat off-screen with no way to reach it, and scrolling right to read "Used" pushed
   "Order this" off the left. The GM could never see the recommendation and its evidence together.
   Lar chose to keep his own column order and pin instead: the answer, the two ways to change it,
   and the item name stay put; the five evidence columns scroll under them.
   Offsets are cumulative and must match the widths above (106 + 106 + 106). */
/* THE HEADINGS STAY PUT WHILE THE LIST SCROLLS (2026-08-28).
   `tr.ohead th` has carried `position: sticky; top: 0` all along and never worked, because sticky
   positions against the nearest SCROLLING ancestor -- and that is `.olist`, which sets overflow-x
   (an element with overflow on one axis scrolls on both). The page was doing the vertical
   scrolling, so the header had nothing to stick to. Giving `.olist` its own height makes it the
   scroller for both axes: the headings hold at the top, the frozen columns hold at the left, and
   the two work together instead of cancelling out. */
/* The height is set at runtime by `sizeList()` in order.js, measured from wherever the list
   actually starts and from the real height of the bottom bar -- both of which move as the summary,
   the search box and the flagged-items banner appear and disappear. The calc() here is only a
   sensible value for the first paint, before the measurement runs. */
.olist { overflow: auto; max-height: calc(100vh - 260px); }
/* THREE FROZEN COLUMNS, NOT FOUR (2026-08-28). `Revised` was dropped -- it repeated the figure
   already bold in "Order this" -- so every offset below it moves left by its width. These MUST
   stay in step with the widths further down: 0 / 106 / 212. "Order this" carries a bare figure
   and "Override" a 84px box, so they are the same 106 (Lar, 2026-08-29). */
.otable th.ostepcell, .otable td.ostepcell { position: sticky; left: 0; z-index: 3; }
.otable th.oover, .otable td.oover { position: sticky; left: 84px; z-index: 3; }
.otable th.oit, .otable td.oit { position: sticky; left: 168px; z-index: 3; }
/* A sticky cell is transparent by default and the scrolling figures would slide underneath it. */
.otable tbody td.ostepcell,
.otable tbody td.oover, .otable tbody td.oit { background: #fff; }
.otable tbody tr.check td.ostepcell,
.otable tbody tr.check td.oover, .otable tbody tr.check td.oit { background: #fffbf0; }
/* The corner cells are frozen BOTH ways -- left and top -- so they must outrank both the
   sticky column (3) and the sticky header rows (4), or the scrolling body slides over them. */
.otable thead th.ostepcell,
.otable thead th.oover, .otable thead th.oit { background: #f3f7f4; z-index: 6; }
/* The edge of the frozen block, so it reads as a pane rather than a coincidence. */
.otable th.oit, .otable td.oit { box-shadow: 1px 0 0 #e2e8e4; }

/* "Order this" is a RESULT, not an input (2026-08-28). It was a real <input readonly> styled like
   the editable boxes beside it, so tapping it focused a field that cannot be typed in. `.oqty` is
   the quantity that will actually be ordered -- override, else revised, else the system's own --
   because the row rendered all three and never said which one won.
   Its type and alignment are set once, in the table block at the foot of this file. */
.dow { display: block; font-size: 11px; color: #6d7873; margin-top: 2px; }
/* This supplier's running total, beside its own dates -- the figure its minimum is judged
   against. Replaces the pooled "N items to order" headline. (Lar, 2026-08-29) */
.dcases { font-size: 15px; font-weight: 700; color: #24422c; margin-left: 18px; white-space: nowrap; }

/* DO THEY NEED TO ORDER AT ALL -- the first thing under each supplier's dates (2026-08-29).
   Three states, three grounds: green they can wait, amber a short list worth a transfer, plain
   they should order. Colour carries the verdict so it reads before the words do. */
.oadvice { padding: 12px 16px; border-radius: 12px; margin: 0 0 10px; line-height: 1.45; }
.oadvice.ok    { background: #eef7f0; border: 1px solid #cfe6d6; color: #1f4a2e; }
.oadvice.think { background: #fdf6e7; border: 1px solid #efdcae; color: #6b4c07; }
.oadvice.act   { background: #f4f7f5; border: 1px solid #dbe3dd; color: #2f3a34; }
.oadvrisk { margin-top: 5px; font-size: 14px; }
.oadvrec  { margin-top: 6px; font-size: 14px; }

/* Find an item. Full width and house-sized, because it is used with a thumb while holding a
   tablet, and because ~120 sorted rows are only searchable if there is something to search with. */
.osearchwrap { margin: 10px 0 6px; }
#oSearch {
  width: 100%; min-height: 56px; font-size: 18px;
  padding: 8px 12px; border: 1px solid #cfd6cf; border-radius: 10px; background: #fff;
}
.osup.dimmed { display: none; }

/* The flagged items, named in the banner and tappable -- naming them saved the hunt through ~120
   rows; tapping finishes it by scrolling there and opening the count box. */
.jumps { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 6px; }
.jumps .jump {
  border: 1px solid #e3d3a4; background: #fff; color: #7a5c0c;
  border-radius: 999px; padding: 8px 14px; min-height: 40px;
  font-size: 14px; font-weight: 600; cursor: pointer; text-align: left;
}
.jumps .jump:hover, .jumps .jump:focus { border-color: #a8710c; color: #5d4609; }

/* The two dates the order is sized on (2026-08-27). Sits directly under the summary, because
   changing either one changes every quantity below it. */
.odates {
  display: flex; align-items: flex-end; flex-wrap: wrap; gap: 14px;
  margin: 0 10px 10px; padding: 10px 12px;
  background: #f3f7f4; border: 1px solid #e2e8e4; border-radius: 10px;
}
.odates label { display: flex; flex-direction: column; font-size: 12px; color: #55605a; gap: 4px; }
.odates input[type="date"] {
  font-size: 15px; padding: 6px 8px; border: 1px solid #cfd8d2; border-radius: 8px; background: #fff;
}
.odates /* The header is one flex row of five unrelated things -- name, two date boxes, the span, the
   total, the button -- all separated by the same 14px gap, so nothing reads as belonging together
   (Lar, 2026-08-29: "this is not formatted nicely"). The span belongs WITH the dates it describes;
   the total and its button belong together and belong at the far right, away from the inputs. */
.dnote { font-size: 13px; color: #3f4a44; padding-bottom: 7px; margin-left: -6px; }
/* Beside the span it follows, not flung to the far edge (Lar, 2026-08-29: "move the cases and
   done with PFG to the right of instead of all the way on the right"). */
.osuphd .dcases { padding-bottom: 6px; }
.osuphd .dtopbtn, .osuphd .dtopup { padding-bottom: 6px; align-self: flex-end; }
.osuphd .dtopup { margin-left: 8px; }
.odates .dnote b { color: #1f7a3d; }

/* ---------------------------------------------------------------------------
   ONE SECTION PER SUPPLIER (2026-08-27). Each carries its own two dates, because
   PFG and Instacart do not share a delivery calendar.
   --------------------------------------------------------------------------- */
.osup { margin: 0 0 22px; }
.osuphd {
  display: flex; align-items: flex-end; flex-wrap: wrap; gap: 14px;
  padding: 10px 12px; margin: 0 10px 6px;
  background: #f3f7f4; border: 1px solid #e2e8e4; border-radius: 10px;
}
.osuphd h2 { margin: 0 8px 0 0; font-size: 18px; align-self: center; }
.osuphd label { display: flex; flex-direction: column; font-size: 12px; color: #55605a; gap: 4px; }
/* Bigger date boxes (Lar, 2026-08-27). These two fields size the whole order, and they are
   filled on a tablet -- they should be the easiest thing on the section to read and to hit. */
.osuphd input[type="date"] {
  font-size: 20px; font-weight: 600; padding: 11px 12px; min-width: 190px;
  border: 1px solid #cfd8d2; border-radius: 10px; background: #fff; color: #24422c;
}
.osuphd input[type="date"]:focus { border-color: #1f7a3d; outline: 2px solid #d8ecdd; }
.osuphd label { font-size: 13px; }
.osuphd .dnote { font-size: 15px; color: #3f4a44; padding-bottom: 11px; }
.osuphd .dnote b { color: #1f7a3d; }
.awaiting { margin: 6px 22px 0; color: #8a938e; }

/* =============================================================================
   ONE TABLE, SET ONCE (2026-08-28)

   Lar: *"the column headings and data are not consistently aligned. And the fonts
   should all be the same - it looks too busy now."*

   WHY IT LOOKED BUSY, and it was not a design choice: this file had been edited in
   three passes and every pass left its rules behind, so the same properties were set
   two and three times at different values and whichever came last quietly won --

       .ostepcell width    160px  then  110px  then  106px
       .ocount width        96px  then  106px
       .onotes font-size  11.5px  then   12px
       th,td text-align    right  declared twice

   -- and an earlier "one size, one alignment" pass failed on the one column that
   mattered, because `.otable td.ostepcell { text-align: left }` outranks the blanket
   `.otable td { text-align: right }` on specificity, not order. The order column stayed
   left-aligned under a right-aligned heading no matter how many times the blanket rule
   was restated.

   THE POINT IS NOT TIDINESS. A GM reads DOWN a column to compare items. Digits cannot
   line up if the four quantity columns are anchored three different ways -- Order this
   left, count and override centred, the rest right. That is the whole cost.

   So: every number right-aligned including the boxes, every column the same width as
   its frozen offset, two type sizes (figures and labels), and each property set once.
   Weight carries what emphasis is needed; size does not.
   ============================================================================= */

/* --- alignment. The only left-aligned thing in the table is the item's name. --- */
/* EVERYTHING LEFT-JUSTIFIED (Lar, 2026-08-29: "if we left justified all the columns it might look
   cleaner"). Right-alignment earns its keep when a column is long enough to read down and compare
   magnitudes; at six columns of one- and two-digit figures it just pushed every number away from
   the label above it and left a ragged gutter on each side. Tabular figures still line the digits
   up, so a column of numbers stays a column. One rule, no exceptions below it. */
.otable th, .otable td            { text-align: left; vertical-align: middle; }
/* Figure columns get 8px of side padding rather than 10 -- 4px per column back across five of
   them, on a table that scrolls. The frozen block and the item cell keep the roomier 10. */
.otable th.n, .otable td.n,
.otable td.have, .otable td.began, .otable td.rate { padding-left: 8px; padding-right: 8px; }
.otable th.oit, .otable td.oit    { text-align: left; }

/* --- widths. These MUST match the sticky offsets above (0 / 106 / 212 / 318), so all
       three frozen figure columns are 106px. `.rev` previously inherited 108px from the
       generic rule, which drifted the frozen block by 2px against its own offsets. --- */
/* The two answer columns are 84, the count box stays 106. All three MUST match the sticky
   offsets above: 0 / 84 / 168. */
.otable th.ostepcell, .otable td.ostepcell,
.otable th.oover,     .otable td.oover   { width: 84px; }
.otable th.ocount,    .otable td.ocount  { width: 106px; }
/* `width` on a table cell is only a suggestion, and once the item cell claims the slack with
   width:100% the browser squeezes everything else to its minimum -- "We think" measured 56px and
   its heading wrapped to three lines. A FLOOR is not negotiable in the same way, so the figure
   columns keep their size and only the name gives. */
.otable th.ostepcell, .otable td.ostepcell,
.otable th.oover,     .otable td.oover  { min-width: 84px; }
.otable th.ocount,    .otable td.ocount,
.otable td.have,      .otable td.need   { min-width: 106px; }

/* THE ITEM NAME TAKES THE SLACK (2026-08-28). The table is width:100%, and dropping from ten
   columns to six left spare width with nowhere to go -- an auto layout handed it to the figure
   columns, so "We think" sat marooned in the middle of a white gap. `width:100%` on one cell in an
   auto table means "absorb whatever is left", and the item name is the only thing on the row that
   genuinely benefits from more room. Every figure column above is pinned, so nothing else moves. */
.otable th.oit, .otable td.oit { width: 100%; }

/* --- one size for every figure; weight, not size, marks the important ones. --- */
.otable td.n,
.otable td.have,
.otable td.began,
.otable td.rate     { font-size: 15px; font-weight: 400; font-variant-numeric: tabular-nums; }
/* The count "We think" was derived from -- evidence, so recessive like the daily rate. */
.otable td.began    { color: #6b746e; }
.otable td.have     { font-weight: 600; }                    /* what the count is compared to */
.otable td.rate     { color: #6b746e; }                      /* explains the order, not acted on */
.otable td.rate .m  { color: #c3cac5; }

/* --- the answer. A figure, not an input: it can only move by typing a count, so it
       must not look pokeable. Right-aligned and single-line, like Revised beside it --
       "system said N" used to stack under it here, which gave this column two lines
       against Revised's one so the two figures could never share a baseline. It now sits
       in the notes under the item name, at the same size as every other note. --- */
.otable td.ostepcell .oqty {
  font-size: 15px; font-weight: 700; text-align: left;
  font-variant-numeric: tabular-nums; color: #24422c;
}
/* The system's original, struck through beside the number that replaced it. Same size as
   every other figure -- it is meant to be readable, not a footnote -- and light enough that
   the live number is obviously the live one. */
/* "3 Cases" with "6 Gallons" beneath it -- the column is 84px and the two do not sit on one line
   (Lar, 2026-08-29). Both lines carry a UNIT, so the second reads at the same size and colour as
   the first rather than as a footnote -- the same call as `.onotes .ounit`: *"not sure why we are
   hiding an important piece of info"*. Weight alone separates the quantity from its translation. */
.otable td.ostepcell .oqty .opack {
  display: block; font-size: 15px; font-weight: 600; color: #24422c;
  line-height: 1.3; margin-top: 1px; white-space: nowrap;
}
.otable td.ostepcell .oqty .was {
  color: #6b746e; font-weight: 400; margin-right: 6px;
  text-decoration-thickness: 1px;
}

/* --- the two boxes that DO take typing. Same size and alignment as the figures they
       sit beside, so the column still reads as a column; 56px tall for a thumb. --- */
.otable td.oover input,
.otable td.ocount input {
  font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums;
  min-height: 56px; width: 84px; text-align: left; padding: 0 9px;
  border-radius: 8px; display: inline-block; box-sizing: border-box;
}
/* The override box lives in an 84px column with 10px of padding each side, so it cannot be 84
   itself -- it would force the column back open and drag the frozen offsets out of step with it.
   It holds at most three digits. (2026-08-29) */
.otable td.oover input { width: 64px; }
.otable td.oover input  { border: 1px solid #cfd8d2; background: #fff; color: #14572a; }
.otable td.ocount input { border: 1px dashed #b9c4bd; background: #fff; }

/* --- taking a count back. The x sits beside the box and only exists once something has been
       typed, so an untouched row carries no extra furniture. Full-height, so it is a real target
       for a thumb rather than a decoration. --- */
.otable td.ocount .ocountwrap {
  display: inline-flex; align-items: center; gap: 4px; justify-content: flex-end;
}
.otable td.ocount .ocountclear {
  border: 0; background: none; cursor: pointer; padding: 0 4px;
  min-height: 56px; line-height: 1; font-size: 20px; color: #8a938e;
}
.otable td.ocount .ocountclear:hover,
.otable td.ocount .ocountclear:focus { color: #b3261e; }
.otable td.ocount input:focus,
.otable td.oover input:focus { border-style: solid; border-color: #1f7a3d; outline: 2px solid #d8ecdd; }

/* COUNT FIRST, THEN OVERRIDE (2026-08-29) -- see syncRowLocks in order.js.
   An override with no count behind it is a quantity nobody can explain, which is the defect the
   old Excel guide had. The box is therefore inert until that row is counted, and it has to LOOK
   inert: a live-looking box that swallows taps is worse than one that plainly is not ready. */
.otable td.oover input:disabled {
  background: #f4f6f5; border-color: #e3e8e5; color: #b3bab6; cursor: not-allowed;
}
/* And once an override stands, the count it was made against is frozen -- pulling the evidence out
   from under the decision is how a quantity loses its reason. Clearing the override releases it. */
.otable td.ocount input[readonly] { background: #f4f6f5; color: #6b746e; border-style: solid; }

/* --- labels: one size for every heading, inheriting each column's own alignment. --- */
.otable tr.ohead th { font-size: 11px; font-weight: 700; letter-spacing: .03em; }

/* --- the item cell: the note now reads at the SAME SIZE as the name (Lar, 2026-08-29: "make Tubs
       the same font size as Food --"). The note carries the UNIT every figure on the row is in, and
       the unit is not a footnote to the name -- a number without it is not an answer. Weight and
       colour still separate them, so the name leads without the unit having to be squinted at. --- */
.otable .oname  { font-size: 15px; font-weight: 600; }
.otable .onotes { font-size: 15px; }

/* GRID LAYOUT (Lar, 16 Oct 2026): Item | Est. on hand | Used per day | Est. needed until next
   delivery | You counted | Order this | Override. Spreadsheet look: lines between every cell, a
   shaded header, only the Item column pinned. Later rules win over the pinning above. */
.otable { border: 1px solid #c9d2cc; border-collapse: collapse; }
.otable th, .otable td { border: 1px solid #d5dcd7; }
.otable tr.ohead th { background: #e8efea; font-weight: 700; color: #26332b; white-space: normal; text-align: center; vertical-align: bottom; }
.otable tr.ohead th.oit { text-align: left; }
.otable tr.ohead th .opt { display: block; font-weight: 400; font-style: normal; font-size: 11px; color: #6b746e; }
.otable th.ostepcell, .otable td.ostepcell, .otable th.oover, .otable td.oover { position: static; box-shadow: none; }
.otable th.oit, .otable td.oit { position: sticky; left: 0; z-index: 3; min-width: 240px; }
.otable tbody tr:nth-child(4n+1) td, .otable tbody tr:nth-child(4n+2) td { background: #fff; }
.otable td.n, .otable td.ocount, .otable td.ostepcell, .otable td.oover { text-align: right; }
.otable td.ostepcell { background: #eef7f0; font-weight: 700; }
.otable td.oover input, .otable td.ocount input { width: 78px; text-align: right; }
.otable td.have, .otable td.perday, .otable td.need { min-width: 96px; }
.osuphd .olast { margin-left: 16px; color: #3d4a42; font-size: 14px; }
.otable td.lastord { min-width: 96px; }
.otable td.oover input, .otable td.ocount input { width: 92px; padding-left: 6px; padding-right: 6px; }
.otable td.lastord { min-width: 110px; } .otable td.lastord .opack { display:block; font-weight:400; font-size:12px; color:#6b746e; }
.otable td.need .opack { display:block; font-weight:400; font-size:12px; color:#6b746e; }
.otable td.bridge { min-width: 112px; } .otable td.bridge .short { color:#a8470c; } .otable td.bridge .ok { color:#7a8a80; font-weight:400; }
.otable td.bridge { min-width: 112px; } .otable td.bridge .short { color:#a8470c; } .otable td.bridge .ok { color:#7a8a80; font-weight:400; }

/* DATE PICKER + EXCEL BAR (16 Oct 2026) */
.otools { display:flex; align-items:center; gap:14px; flex-wrap:wrap; padding:10px 12px; background:#f3f7f4; border-bottom:1px solid #d5dcd7; }
.otools label { font-weight:600; color:#26332b; }
.otools select { margin-left:8px; padding:7px 10px; font-size:15px; border:1px solid #c9d2cc; border-radius:8px; background:#fff; }
.otools button { padding:8px 14px; border:1px solid #c9d2cc; border-radius:8px; background:#fff; font-weight:600; cursor:pointer; }
.ohist { padding:10px 12px; overflow:auto; }
.ohist table { border-collapse:collapse; background:#fff; }
.ohist th, .ohist td { border:1px solid #d5dcd7; padding:7px 10px; white-space:nowrap; text-align:right; }
.ohist th { background:#e8efea; text-align:center; }
.ohist td.l, .ohist th.l { text-align:left; }
.ohist tr.sup td { background:#f3f7f4; font-weight:700; text-align:left; }
.ohist .note { margin:0 0 10px; color:#3d4a42; }
.osup.vhide { display:none; }

/* THE PFG REVIEW PAGE AS A GRID (16 Oct 2026) -- same look as the order screen's grid */
#lines { border-collapse:collapse; width:100%; background:#fff; border:1px solid #c9d2cc; }
#lines th, #lines td { border:1px solid #d5dcd7; padding:8px 10px; vertical-align:middle; }
#lines thead th { background:#e8efea; font-weight:700; color:#26332b; text-align:center; vertical-align:bottom; }
#lines thead th.l, #lines td.l { text-align:left; }
#lines thead th .opt { display:block; font-weight:400; font-style:normal; font-size:11px; color:#6b746e; }
#lines td.num { text-align:right; font-variant-numeric:tabular-nums; }
#lines td.num .opack { display:block; font-weight:400; font-size:12px; color:#6b746e; }
#lines td.ordercell { background:#eef7f0; }
#lines td.ordercell input { width:84px; text-align:right; }
#lines .munit { font-weight:700; color:#26332b; }
#lines .short { color:#a8470c; }
#lines .ok { color:#7a8a80; }
#lines tr.catrow td { background:#f3f7f4; }

.linesbox { overflow-x:auto; -webkit-overflow-scrolling:touch; }
#lines { min-width:820px; }
#lines td.l, #lines th.l { min-width:210px; }
#lines td.num, #lines th.num { min-width:84px; }

#oBaskets .basket.minor { padding:6px 12px; cursor:pointer; min-height:0; }
#oBaskets .basket.minor > *:not(b) { display:none; }
#oBaskets .basket.minor::after { content:" - tap to open"; color:#6b746e; font-size:12px; }

.otable td.unit, .otable th.unit { text-align:left; min-width:76px; color:#3d4a42; font-weight:600; }
#lines td.unit { text-align:left; color:#3d4a42; font-weight:600; min-width:76px; }

.otable th.want, .otable td.need { min-width:132px; }

.odage { color:#6b746e; font-weight:400; margin-left:6px; }
.odstale { color:#a8710c; font-weight:700; margin-left:6px; }

/* THE REVIEW PAGE'S COLUMNS AND LOCKED HEADING (Lar, 18 Oct 2026: "the column widths make no sense", "the headings need to lock").
   Fixed layout so the item name gets the room and the number columns are even; the heading stays on screen while the list scrolls
   (a sticky heading only works when the box around the table does not itself scroll, so wide screens drop that box's scrolling). */
#lines { table-layout:fixed; min-width:700px; }
#lines th:nth-child(1), #lines td:nth-child(1) { width:18.18%; }     /* Item = two units wide */
#lines th:nth-child(n+2), #lines td:nth-child(n+2) { width:9.09%; }   /* each of the nine other columns = HALF the Item column (Lar, 18 Oct 2026): 2 + 9 x 1 = 11 parts */
#lines td.l, #lines th.l, #lines td.num, #lines th.num, #lines td.unit { min-width:0; }
#lines input.cnt { display:block; width:100%; box-sizing:border-box; margin-top:4px; padding:3px 4px; font-size:13px; text-align:right; }
#lines td.oover input { width:100%; box-sizing:border-box; text-align:right; }
#lines td.ostepcell { background:#eef7f0; font-weight:700; }
#lines th.ostepcell { background:#dcebe0; }
#lines s.was.hidden { display:none; }
#lines s.was { color:#8a948d; margin-right:6px; }
@media (min-width:700px) {
  .linesbox { overflow:visible; }
  #lines thead th { position:sticky; top:0; z-index:3; }
}

#review header.topbar { position:static; }   /* the green bar scrolls away on the review page so the locked column headings sit at the very top */
#lines th:nth-child(n+2), #lines td:nth-child(n+2) { padding-left:4px; padding-right:4px; }
#lines thead th:nth-child(n+2) { font-size:12.5px; }
#lines tfoot td { background:#e8efea; border-top:2px solid #9fb1a5; font-size:15px; }
#lines tfoot td.ostepcell { background:#dcebe0; }
#lines tfoot td.oover { background:#fff7df; }
#lines tfoot .opack { display:block; font-weight:400; font-size:10px; line-height:1.1; color:#6b746e; }
#lines thead th.oover { font-size:11.5px; letter-spacing:-0.2px; }
#lines span.cdiff { display:block; font-size:10px; line-height:1.15; color:#6b746e; margin-top:2px; }
#lines span.cdiff.hidden { display:none; }
#lines span.cdiff.off { color:#a8470c; font-weight:700; }
/* A WIDE SCREEN MUST NOT STRETCH THE ITEM COLUMN (Lar, 18 Oct 2026: "look what you did"): the table stops at 980px, the nine narrow columns stay next to the item name. */
#lines { max-width:980px; }

/* THE COMPUTER LAYOUT (Lar, 18 Oct 2026: the tablet layout "looks good for the tablet but not for the computer ... for the computer we want to
   use more screen space, item should be wider and the other columns a little bit wider"). Only a wide screen with a mouse (not a touch tablet)
   gets it, so the Android tablet keeps the layout above whatever its width reports. The nine narrow columns go from 89px to 100px; Item takes the
   rest, up to a 1700px table. */
@media (min-width:1400px) and (pointer:fine) {
  #lines { max-width:2000px; }
  #lines th:nth-child(1), #lines td:nth-child(1) { width:auto; }
  #lines th:nth-child(n+2), #lines td:nth-child(n+2) { width:125px; }   /* 100px -> 125px: the nine non-item columns 25% wider on the computer (Lar, 18 Oct 2026) */
}

/* THE DATE BOXES ARE NOT PAGE-WIDE (Lar, 18 Oct 2026: "why put the date picker all the way right"). On a wide screen the two date boxes and the button
   stretched across the whole page and the calendar icon sat at the far edge; the card now stops at 520px so the icon sits beside the date. */
@media (min-width:700px) {
  #dates { max-width:520px; }
}

/* THE SUMMARY TEXT IS 20% BIGGER (Lar, 18 Oct 2026: "increase the size of this text 20%"): the "Not on this order" line and the card with the case total,
   the count note and the sales-forecast note. Was 13px / 16px; now 15.6px / 19.2px. */
#dropped, #countNote, #factorNote { font-size:15.6px; }
#total, #minNote { font-size:19.2px; }
/* ported from Yvento (edits 88, 91) */
    #total{font-size:22px}
    table.lines th.num, table.lines th.l{white-space:normal;line-height:1.2;vertical-align:bottom;min-width:64px;font-size:11.5px;letter-spacing:.01em;padding:10px 5px}
    table.lines th.ostepcell{min-width:88px}
    .cfnote{margin:8px 14px;padding:10px 12px;border-radius:12px;background:#fff3cd;border:1px solid #e0c36a;color:#664d03;font-weight:700}
    tr.countfirst td{background:#fff8d6}
    .cfl{display:inline-block;margin:2px 0;padding:1px 8px;border-radius:10px;background:#f2c94c;color:#3d2f00;font-size:12px;font-weight:700}

    tr.countfirst td{background:#fff8d6}
    table.lines tr.fillrow td{background:#e3f0fc}
