/* One design system for every screen, editor and dialog. Tokens and base typography first, then the shared
   components (buttons, fields, cards, section heads, chips, tables, tabs, notices, dialogs, toasts) and the
   inventory screens that were built with them. Module sheets (billing, purchase, documents, workspace) add
   layout only and never redefine these tokens.
   Text has four roles and every rule that sets a text colour uses one of them; `node scripts/check-text-contrast.mjs`
   checks their contrast on the paper and surface backgrounds:
     --ink       primary: headings, body copy, names, values, figures, the anchor of a row
     --ink-soft  secondary: labels that name a value (column headers, card labels, field labels, dt, eyebrows,
                 fact labels, mobile data-labels), inactive tabs
     --muted     tertiary: notes, hints, sub-lines, timestamps, empty states, footers, decorative icons
     --faint     placeholders and disabled text only
   Pages are fluid to the window: nothing sets a max-width on a screen. Every list and detail table is a .list-table
   (see below); only editors with inputs and the printed documents are not. */
:root{--font:'Avenir Next','Segoe UI',system-ui,Helvetica,Arial,sans-serif;--ink:#0f1a15;--ink-soft:#243529;--muted:#46584b;--faint:#758476;--paper:#f4f3ed;--surface:#fff;--surface-soft:#f8faf4;--line:#dce2d8;--line-soft:#edf0e9;--green:#23684c;--green-dark:#174d38;--green-ink:#205d43;--green-tint:#e5f0dd;--green-soft:#f0f6eb;--green-line:#c9dbbd;--lime:#8dab66;--sidebar-bg:#123c30;--sidebar-ink:#e1e9df;--sidebar-muted:#b3c6b8;--sidebar-hover:#245442;--sidebar-active:#d4e9ac;--sidebar-active-ink:#173c2b;--sidebar-line:#416151;--amber-ink:#6f5a23;--amber-tint:#f3eacb;--amber-soft:#fcf8ea;--amber-line:#eadfb4;--blue-ink:#1e4e7a;--blue-tint:#e3edf6;--blue:#2e6a9c;--blue-line:#c4d7e9;--blue-soft:#f3f7fb;--amber-edge:#c9a64a;--red:#9d3027;--red-ink:#7d2a20;--red-tint:#fbeeea;--red-line:#efc9bf;--focus:#4d8041;--radius:16px;--radius-sm:9px;--control:42px;--control-text-top:calc((var(--control) - 21px)/2);--shadow-pop:0 8px 24px #2638201c;--sidebar-width:238px;--side-column:360px;--page-gutter:32px;--section-gap:24px;color-scheme:light}
*,*::before,*::after{box-sizing:border-box}
html{font-family:var(--font);font-size:15px;line-height:1.5;color:var(--ink);font-synthesis:none;-webkit-text-size-adjust:100%}
body{margin:0;background:var(--paper)}
h1,h2,h3,h4,p,dl,dd,figure,fieldset{margin:0}
fieldset{padding:0;border:0;min-width:0}
h1,h2,h3,h4,th,strong,b,button,input,select,textarea,legend,summary{font-weight:400}
h1{font-size:30px;line-height:1.2;letter-spacing:-.8px;font-weight:650}
h2{font-size:18px;line-height:1.35;letter-spacing:-.2px}
h3{font-size:15px;line-height:1.4}
h4{font-size:14px;line-height:1.4}
a{color:var(--green);text-underline-offset:3px}
a:hover{color:var(--green-dark)}
:where(button,input,select,textarea){font:inherit;color:inherit;margin:0}
:where(button){cursor:pointer;background:none;border:0;padding:0;-webkit-tap-highlight-color:transparent}
button:disabled{cursor:not-allowed}
button,a,input,select,textarea,summary{touch-action:manipulation}
svg{width:20px;height:20px;display:block;flex:none}
[data-icon]{display:inline-flex;align-items:center}
[hidden]{display:none!important}
:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
::placeholder{color:var(--faint);opacity:1}
/* What is one word to its reader is never broken across lines: a phone number (.tel), a document's number, a short date (.nw). */
.tel,.nw{white-space:nowrap}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.poe-num{text-align:right;font-variant-numeric:tabular-nums}
.muted,.poe-sub,.doc-cur{color:var(--muted)}
.warning-text{color:var(--red)}
/* The refusal said beside an action a role is not offered (a disabled button in a page head: the server would refuse it). */
.action-note{flex:1 1 260px;max-width:460px;font-size:14.5px;line-height:1.45;color:var(--red)}

/* Buttons (README "Buttons"; scripts/check-buttons.mjs). Three kinds, one name each: .button (the oval; .primary is the one
   main action of a view or a dialog, .danger destroys or cancels a record, .small is its size inside a card, a row, a table or
   a card's toolbar; .large is the sign-in page's full-width step, 2026-10-07), .text-btn (a quiet action that reads as a link; .small, .danger) and .icon-button (round, icon only, named
   by aria-label; .danger reddens on hover). A button's size is said by its class, never by where it sits: only this block
   sets a button's metrics, and no other class name draws a button. */
.button{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:var(--control);padding:9px 18px;border:1px solid #d3dccf;border-radius:9px;background:var(--surface);color:var(--ink);font-size:14px;font-weight:600;line-height:1.25;white-space:nowrap;text-decoration:none;cursor:pointer;flex:none;box-shadow:0 1px 2px #17392b0a;transition:background-color .15s,border-color .15s,color .15s}
.button:hover{background:#f0f5eb;border-color:#aab99e;color:var(--ink)}
.button.primary{background:var(--green);border-color:var(--green);color:#fff;box-shadow:0 4px 9px #174b3520}
.button.primary:hover{background:var(--green-dark);border-color:var(--green-dark);color:#fff}
.button.danger{color:var(--red);border-color:#dfbeb8}
.button.danger:hover{background:var(--red-tint);border-color:#cc9d94;color:var(--red-ink)}
.button.danger.primary{background:var(--red);border-color:var(--red);color:#fff}
.button.danger.primary:hover{background:var(--red-ink);border-color:var(--red-ink);color:#fff}
.button.danger:focus-visible{outline-color:var(--red)}
.button.small{min-height:34px;padding:6px 13px;font-size:13px}
.button.large{width:100%;min-height:52px;padding:12px 20px;border-radius:10px;font-size:16px}
.button.large[aria-busy=true]{opacity:.85;cursor:progress}
.text-btn.large{font-size:15px}
.button svg,.text-btn svg{width:16px;height:16px}
.button:disabled,.button[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}
.button.signout-button{display:flex;width:100%}
.text-btn,.page-back>a,.page-back>button{display:inline-flex;align-items:center;gap:6px;min-height:0;padding:0;border:0;border-radius:0;background:none;color:var(--green);font-size:14px;line-height:1.5;text-decoration:underline;text-decoration-color:#a9c9ad;text-underline-offset:3px;cursor:pointer;white-space:normal}
.text-btn:hover,.page-back>a:hover,.page-back>button:hover{color:var(--green-dark);text-decoration-color:currentColor}
/* Beside small text (a note, a card's foot, a timeline) the text button takes that text's size. */
.text-btn.small{font-size:13px}
/* A destructive text button (remove a payment, delete a line): red ink, same shape. */
.text-btn.danger{color:var(--red);text-decoration-color:var(--red-line)}
.text-btn.danger:hover{color:var(--red-ink);text-decoration-color:currentColor}
.icon-button{display:inline-grid;place-items:center;width:36px;height:36px;min-height:0;padding:0;border:0;border-radius:999px;background:transparent;color:var(--muted);font-size:22px;line-height:1;flex:none}
.icon-button:hover{background:#f0f5eb;color:var(--ink)}
.icon-button.danger:hover{color:var(--red)}
.icon-button svg{width:18px;height:18px}
.icon-button.small{width:26px;height:26px}
.icon-button.small svg{width:14px;height:14px}

/* Fields: one input, one label, one hint, one inline error. */
:where(input:not([type=checkbox]):not([type=radio]):not([type=range]),select,textarea),.select-trigger{display:block;width:100%;min-height:var(--control);padding:9px 11px;border:1px solid #ced9cd;border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-size:15px;line-height:1.35;box-shadow:none;transition:border-color .16s,box-shadow .16s}
input:hover,select:hover,textarea:hover,.select-trigger:hover{border-color:#aab99e}
input:focus,select:focus,textarea:focus,input:focus-visible,select:focus-visible,textarea:focus-visible,.select-trigger:focus,.select-trigger:focus-visible,.select-trigger[aria-expanded=true]{outline:none;border-color:var(--focus);box-shadow:inset 0 0 0 1px var(--focus)}
input[readonly],input:disabled,select:disabled,textarea:disabled,.select-trigger:disabled{background:#f7f9f4;color:var(--muted);border-color:#e2e7db;cursor:default}
input[aria-invalid=true],select[aria-invalid=true],textarea[aria-invalid=true],.select-trigger[aria-invalid=true]{border-color:var(--red)}
textarea{min-height:76px;resize:vertical;line-height:1.5}
input[type=checkbox],input[type=radio]{width:17px;height:17px;min-height:0;margin:0;accent-color:var(--green);flex:none}
input[type=checkbox]:focus-visible,input[type=radio]:focus-visible{outline:2px solid var(--focus);outline-offset:2px;box-shadow:none}
/* A choice between two ways of doing one thing (a quote's Accept: from stock or as a direct load, owner 2026-10-06): radio cards, the
   chosen one on the green tint; the name in weight, what it does under it at the reading size. */
.choice-group{border:0;margin:0;padding:0;min-width:0;display:grid;gap:10px}
.choice-group legend{padding:0;margin-bottom:8px;font-size:14.5px;font-weight:600;color:var(--ink)}
.choice{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;align-items:start;padding:12px 14px;border:1px solid var(--line);border-radius:12px;background:var(--surface);cursor:pointer}
.choice:has(input:checked){border-color:var(--green);background:var(--green-soft)}
.choice input{margin-top:3px}
.choice b{display:block;font-weight:600;color:var(--ink)}
.choice small{display:block;font-size:14px;line-height:1.45;color:var(--ink-soft)}
input[type=date]{padding-right:8px}
input[type=file]{padding:8px;font-size:14px}
input[type=number]{font-variant-numeric:tabular-nums}
input[type=search]{-webkit-appearance:none;appearance:none}
label{font-size:14px;color:var(--ink-soft)}
.field{display:block;margin:0 0 16px;min-width:0}
.field:last-child{margin-bottom:0}
/* A field is label, control, hint, error. Inside a purchase-order field grid every field spans the same four row tracks
   through subgrid, so a label that wraps never pushes its control out of line with its neighbours. The grid has no row
   gap (a gap would also surround the empty hint and error tracks); the space between rows is the label's top padding,
   pulled back at the top of the grid by its negative margin. */
.poe-field{display:grid;align-content:start;margin:0;min-width:0}
.poe-grid-2>.poe-field,.poe-grid-3>.poe-field{grid-template-rows:subgrid;grid-row:span 4}
.poe-grid-2>.poe-field>span:not(.select-shell),.poe-grid-3>.poe-field>span:not(.select-shell){padding-top:14px}
.poe-grid-2>div:not(.poe-field),.poe-grid-3>div:not(.poe-field){margin-top:14px}
.field>span,label>span,.poe-label{display:block;font-size:14px;color:var(--ink-soft);line-height:1.4;margin-bottom:6px}
/* A fieldset's legend titles a group of fields (Pack, Usual order terms): ink at the reading size, 600, never a grey label. */
.pack-builder legend{display:block;font-size:15px;font-weight:600;color:var(--ink);line-height:1.4;margin-bottom:6px}
.poe-field>span{margin-bottom:6px}
/* A fact among fields that is READ, never picked (who sells and in which currency: they follow the customer's country): its label as
   the fields beside it, its value in ink at 600 on the controls' line. `field-read` on the .field or .poe-field, the value in <strong>. */
.field-read>span{display:block;font-size:14px;color:var(--ink-soft);line-height:1.4;margin-bottom:6px}
/* A value read inside a form's grid, in a field's place (the currency of a storage bill or charge, 2026-09-29): the label as the fields' and the value at the control's height. */
.poe-field>strong.read-value{display:flex;align-items:center;min-height:var(--control);font-size:15.5px;font-weight:600;line-height:1.35;color:var(--ink)}
.field-read>strong{display:flex;align-items:center;min-height:var(--control);font-size:15.5px;font-weight:600;line-height:1.35;color:var(--ink)}
.field-read>strong:empty::before{content:"\2014";font-weight:400;color:var(--muted)}
.field-read>strong .text-btn{font-weight:500}/* a fact's Change (the PO editor) is not read at the value's weight */
.field small,.field-note,.editor-hint,.poe-hint{display:block;font-size:13px;line-height:1.5;color:var(--muted);margin-top:6px}
.poe-hint b,.editor-hint b{color:var(--ink-soft)}
.poe-hint:empty,.poe-error:empty,.error:empty{display:none}
.field-pair,.form-grid,.poe-grid-2,.poe-grid-3{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px 16px}
.form-grid.three,.poe-grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}
/* Purchase-order grids: no row gap (the labels carry the row spacing, see .poe-field above). Must follow the gap shorthand. */
.poe-grid-2,.poe-grid-3{row-gap:0;margin-top:-14px}
.span-all,.lc-span2{grid-column:1/-1}
/* A field inside a field grid is a grid item: the grid's gap is the space between its fields, never a field's own margin (a
   margin inside a grid adds to the gap, so a pair that stacks on a narrow screen had one gap of 30px between its two fields and
   none after it). A pair is spaced from what follows like a field (16px), and its row gap is the same 16px, side by side or stacked. */
.field-pair>.field,.form-grid>.field{margin:0}
/* A form written as several grids, one after another, reads as one: the rows of two grids are as far apart as the rows of one. */
.form-grid+.form-grid,.form-grid+[hidden]+.form-grid{margin-top:14px}
.field-pair{row-gap:16px;margin:0 0 16px}
.field-pair:last-child{margin-bottom:0}
/* A supplier's (or another party's) name where it is read opens its own page: the name keeps its weight, green as a link. */
.party-link{text-decoration:none}
.party-link:hover{text-decoration:underline}
.check-label,.lc-check{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--ink);margin:0}
/* A tick that is required says its problem on a line of its own under the words (the claim window's Other cases, 2026-10-12). */
.check-label{flex-wrap:wrap}.check-label>.poe-error{flex-basis:100%;margin-top:-4px}
.poe-error,.error{display:block;color:var(--red);font-size:13px;margin-top:6px}
/* A problem marked on its field (FWLayout.mark, owner 2026-10-01) is red wherever the field sits: a Settings .field, a window's label, a cell. */
.field .poe-error[data-mark],label .poe-error[data-mark],td .poe-error[data-mark]{color:var(--red);font-size:13.5px}

/* Surfaces: one card, one soft inner panel. */
.summary,.poe-card,.panel,.lc-summary,.shipment-panel{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);min-width:0;box-shadow:0 3px 12px #203c2a08}
.poe-card>.poe-card-head:first-child{margin:-24px -24px 18px;padding:16px 24px;background:var(--surface-soft);border-bottom:1px solid var(--line-soft);border-radius:var(--radius) var(--radius) 0 0}
.poe-card{padding:24px}
.panel{overflow:hidden;margin-bottom:var(--section-gap)}
.panel-top{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;padding:16px 24px;border-bottom:1px solid var(--line);min-height:64px}
.panel-body{padding:24px}
.shipment-panel{overflow:hidden}
.balance,.reservation,.lc-note,.party-summary,.poe-inco,.pack-preview{background:var(--surface-soft);border:1px solid #e6ebe3;border-radius:10px}
/* A party on a document (a supplier, a customer, where it is delivered) is picked and then READ in this quiet panel with one
   Edit; it is never retyped into boxes on the document. The PO editor and the invoice editor share it. The text is read,
   so it is ink at 15px with the party's name at 16px in weight; only the lines under the rule (.poe-sub: a series, usual
   terms, where a delivery address came from) are quiet. The contact and the phone number share a line while both fit (.party-contact); the number (.tel) never breaks across two. A fact nobody
   recorded is said once, quietly (.party-empty). */
.party-summary{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-top:12px;padding:12px 14px;font-size:15px;line-height:1.55;color:var(--ink);overflow-wrap:anywhere}
.party-summary>div{min-width:0}
.party-summary>.text-btn{flex:none;white-space:nowrap}
.party-summary strong{display:block;margin-bottom:3px;font-size:16px;font-weight:600;color:var(--ink)}
.party-contact{display:flex;flex-wrap:wrap;column-gap:14px}
.party-summary .tel{white-space:nowrap}
.party-summary .poe-sub{margin-top:10px;padding-top:10px;border-top:1px solid var(--line-soft);font-size:14.5px;line-height:1.5;color:var(--ink-soft)}
.party-summary .poe-sub+.poe-sub{margin-top:2px;padding-top:0;border-top:0}
.party-empty{margin:0;color:var(--muted)}
/* A percent says it is a percent: the sign sits inside the field's right edge (a payment stage on an order, on a supplier's
   usual terms), never a "%" placeholder that vanishes with the first digit. */
.poe-pct{position:relative;display:block}
.poe-pct input{padding-right:28px;text-align:right}
.poe-pct i{position:absolute;right:11px;top:50%;transform:translateY(-50%);font-style:normal;font-size:15px;color:var(--muted);pointer-events:none}

/* Section heads inside cards. */
.poe-card-head,.section-heading{display:flex;align-items:center;justify-content:space-between;gap:12px 16px;flex-wrap:wrap;margin-bottom:16px;min-width:0}
.panel-top h2,.poe-card-head h2,.section-heading h2,.poe-card>h2{font-size:18px;letter-spacing:-.2px;min-width:0;margin:0}
.poe-card>h2,.poe-order>div>h2,.panel-body>h2{margin-bottom:16px}
.section-heading h3,.customer-address-grid h3{font-size:15px}
.poe-card-head .poe-sub,.panel-top .muted{font-size:13px;color:var(--muted);margin:4px 0 0}

/* Count badges and icon tiles. */
.filter-count{display:inline-grid;place-items:center;min-width:22px;height:22px;padding:0 6px;border-radius:999px;background:var(--green-tint);color:var(--green-ink);font-size:12px;line-height:1;letter-spacing:0;font-variant-numeric:tabular-nums}

/* Chips: one shape, five tones. */
.status,.poe-status,.poe-pill,.tag{display:inline-block;padding:3px 9px;border:0;border-radius:6px;background:#e9eee4;color:var(--ink-soft);font-size:12px;font-weight:600;line-height:1.5;white-space:nowrap;vertical-align:middle;letter-spacing:0;cursor:default}
.poe-pill{font-size:13px}
.tag{margin-left:5px}
.tag.muted{color:var(--muted)}
.status.paid,.poe-status.sent,.poe-status.confirmed,.poe-status.shipped,.poe-status.closed,.poe-pill.closed,.poe-pill.saved,.poe-pill.sent,.poe-pill.confirmed,.poe-pill.shipped{background:var(--green-tint);color:var(--green-ink)}
.status.partial,.poe-status.draft,.poe-status.partially_received,.poe-status.settle,.poe-pill.settle,.poe-pill.dirty,.poe-pill.draft,.tag.orange{background:var(--amber-tint);color:var(--amber-ink)}
.poe-status.received,.poe-pill.received{background:var(--blue-tint);color:var(--blue-ink)}
.status.void,.status.stopped,.poe-status.cancelled,.poe-pill.cancelled{background:var(--red-tint);color:var(--red-ink)}

/* Tables: one header, one row, one footer. A column is classed by what it holds, never by how it aligns:
     (no class)    text: left, header left
     .col-num      a count, a measure or an amount: right with tabular figures, header right
     .col-status   a chip and its note: left, the chip level with the row's first line
     .col-actions  buttons or the row arrow: right, header right (an "Actions" label or nothing)
     .col-tight    never wraps  ·  .col-wide  shows from 1480px only
   Header and cells of a column carry the same classes. Cells are top-aligned with equal padding so the first lines of a
   row share one baseline whether a cell holds one line or two. Only this sheet sets text-align on th/td; module sheets
   set widths and paddings (the printed purchase-order sheet, .pp-*, keeps its own document style).
   Every cell of a .list-table except the first (the row's anchor), .col-actions and .empty carries
   data-label="<its column header>": on a narrow workspace the table becomes stacked cards (see "Stacked list tables"
   at the end of this sheet) and the label is what names each value.
   `node scripts/check-tables.mjs` (in npm run lint) fails on a legacy alignment class, a header whose classes differ
   from its cells, a list-table cell with no data-label, or a module sheet aligning cells. */
.table-scroll,.table-wrap,.poe-conflict{overflow-x:auto;overscroll-behavior-x:contain}
table{border-collapse:collapse;width:100%;text-align:left}
th{font-size:12px;color:var(--ink-soft);text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);background:transparent;white-space:nowrap;vertical-align:bottom;letter-spacing:0;text-transform:none}
td{padding:14px 12px;font-size:14px;border-bottom:1px solid var(--line-soft);vertical-align:top}
tbody tr:last-child td{border-bottom:0}
th.col-num,td.col-num{text-align:right;font-variant-numeric:tabular-nums}
th.col-actions,td.col-actions{text-align:right}
td.col-actions .actions{justify-content:flex-end}
/* A button keeps its label on one line, so an actions cell is measured at the width its buttons really take. */
td.col-actions .text-btn,td.col-actions .button{white-space:nowrap}
td.col-status>.status,td.col-status>.poe-status{margin-top:2px}
td small{display:block;font-size:12.5px;color:var(--muted);margin-top:3px;line-height:1.5}
td strong{color:var(--ink)}
/* List tables (.list-table): a cell is the fact and one or two lines under it. READING RULE (owner, 2026-09-20 and 09-21:
   "bland, hard to read"): what names the row and what it comes to carry weight (600) at 15.5–16.5px (the anchor, a cell's
   strong, the figure), the line under them is ink at 14.5px, only a third line is quieter (ink-soft, 14px). THE HEADER IS THE ONE
   BAND OF A TABLE (owner, 2026-09-28: "headers are blending in and hard to read"): ink capitals at 12.5px on --green-tint, closed by
   a green rule; nothing in the body is tinted as strongly, so a heading row inside a table (a product, a ledger's month) is a quieter
   band or a rule. Nothing a row says is small grey. NO LINE IS CUT with an ellipsis: lines are as wide as
   their column and wrap; a dotted line drawn by FWLayout.facts wraps between its facts, never inside a short one (.fact).
   The first cell carries the row's anchor (.row-anchor). Text columns are
   left-aligned, figures and money right-aligned (.col-num), chips left (.col-status), buttons right (.col-actions),
   header and cell alike. Spare width is shared by every column in proportion to its content and never capped. An empty
   figure is a muted dash (<span class="none">—</span>); an empty text value is one muted line (.none), never a dash with
   a reason under it. The footer states the count and nothing else. Editors and printed documents are not list tables. */
.list-table th{padding-top:13px;padding-bottom:13px;font-size:12.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--ink);background:var(--green-tint);border-bottom:1px solid var(--green-line)}
.list-table td{padding-top:18px;padding-bottom:18px}
/* A list read for scanning (owner, 2026-09-28: Shipment inventory, "compact the row"): .list-table.compact keeps the reading sizes and
   takes the air out of a row: less padding, and the lines under a fact sit closer to it. */
.list-table.compact td{padding-top:11px;padding-bottom:11px}
.list-table.compact td small{margin-top:1px;line-height:1.4}
.list-table.compact td small+small{margin-top:0}
.list-table.compact td.col-num .progress{margin-top:5px}
.list-table.compact td.col-status small{margin-top:3px}
.list-table td strong,.list-table td small{display:block;max-width:none;overflow-wrap:break-word}
.list-table td strong{font-size:15.5px;font-weight:600;line-height:1.4}
.list-table td.col-num strong{font-size:16.5px}
.list-table td small{margin-top:4px;font-size:14.5px;line-height:1.45;color:var(--ink)}
.list-table td small+small{margin-top:2px;font-size:14px;color:var(--ink-soft)}
/* A dotted line of facts (FWLayout.facts): it wraps between its facts, and the dot belongs to the gap before a fact, so a line never
   ends or opens on one (the dot before the first fact of a line falls outside the line's edge, which cuts it). */
.facts{display:flex;flex-wrap:wrap;column-gap:1.1em;min-width:0;max-width:100%;overflow:hidden}
/* A fact stays whole while its line has room for it; one wider than the line itself wraps inside it, so nothing is ever cut. */
.fact{position:relative;flex:0 1 auto;min-width:0;overflow-wrap:anywhere}
.fact::before{content:'\00B7';position:absolute;right:100%;width:1.1em;text-align:center}
.list-table .doc-cur{font-size:13px;font-weight:400;color:var(--ink-soft)}
.list-table .status,.list-table .poe-status{font-size:12.5px;font-weight:600}
.list-table .col-tight,.list-table td.col-num,.list-table th.col-num{white-space:nowrap}
/* A figure column that holds a list of goods ("12 cases Papaya Maradol + 20 boxes Persian limes") wraps like the words it is. */
.list-table td.col-num.goods,.list-table td.col-num.goods *{white-space:normal}
/* Which company a row belongs to (owner, 2026-09-23: two companies, separate books). Shown only while a list shows both
   companies (FWLayout.companyMark): a small quiet mark after the chip, or after a strip figure's currency; the company is a
   fact of the row, not a state, so it is text in a thin frame, never a chip, and it is drawn the same everywhere. */
.co-mark{display:inline-block;margin-left:6px;padding:1px 6px;border:1px solid var(--line);border-radius:6px;font-size:11.5px;font-weight:600;line-height:1.4;letter-spacing:.5px;text-transform:uppercase;color:var(--ink-soft);vertical-align:middle;white-space:nowrap}
.currency-total .co-mark{margin-left:4px}
/* A fact that is still to be set (a company's payment instructions): amber ink, wherever a read-only list says it. */
dd.missing,span.missing{color:var(--amber-ink)}
/* A card head's count that asks for something (the quote's items before a currency is chosen, prices cleared): read at the reading size in amber. */
.poe-card-head .lc-count.warn{font-size:14.5px;font-weight:600;color:var(--amber-ink)}
/* The filters of a toolbar (a month, a warehouse, the company): dropdowns and the search on one line, wrapping on a phone. */
.toolbar-filters{display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-width:0}
.toolbar-filters>label,.toolbar-filters>.select-shell{min-width:0}
#page-actions .select-shell{width:auto;flex:0 0 auto}
#page-actions select.company-filter{min-width:190px}
.row-anchor{display:inline;padding:0;border:0;background:transparent;color:var(--green-ink);font-size:16.5px;font-weight:600;letter-spacing:-.2px;text-align:left;text-decoration:none;cursor:pointer}
.row-anchor:hover,.row-anchor:focus-visible{color:var(--ink);text-decoration:underline}
.none{color:var(--muted);white-space:nowrap}
/* A state chip on a cell's second line (shipment inventory) sits inside the line box. */
.list-table td small .tag{margin:0 6px 0 0;padding:0 8px}
/* A call to action in a figure cell stays on one line. */
.list-table td .text-btn{white-space:nowrap}
@media(max-width:1479px){.list-table .col-wide{display:none}}
.shipment-panel th:first-child,.shipment-panel td:first-child,.panel th:first-child,.panel td:first-child{padding-left:24px}
.shipment-panel th:last-child,.shipment-panel td:last-child,.panel th:last-child,.panel td:last-child{padding-right:24px}
/* An editor's table sits flush with its card's edges; a .list-table keeps its cell padding, because its header is a tinted band and
   the words must sit inside it, not on its edge (owner, 2026-09-29: Trace stock's lots table). */
.poe-card table:not(.list-table) th:first-child,.poe-card table:not(.list-table) td:first-child,.settings-content table:not(.list-table) th:first-child,.settings-content table:not(.list-table) td:first-child{padding-left:0}
.poe-card table:not(.list-table) th:last-child,.poe-card table:not(.list-table) td:last-child,.settings-content table:not(.list-table) th:last-child,.settings-content table:not(.list-table) td:last-child{padding-right:0}
/* The row is the control (layout.js): every list-table row that opens by its name reads as one control, not one word in it. */
tr[data-doc-row],tr[data-open],tr[data-lot-row],tr[data-order-row],tr[data-sales-row],tr[data-quote-row],tr[data-claim-row],tr[data-recall-row],table.list-table tbody tr:has(.row-anchor,td:first-child a[href]){cursor:pointer;transition:background .15s}
tr[data-doc-row]:hover,tr[data-doc-row]:focus-within,tr[data-open]:hover,tr[data-lot-row]:hover,tr[data-lot-row]:focus-within,tr[data-order-row]:hover,tr[data-sales-row]:hover,tr[data-quote-row]:hover,tr[data-claim-row]:hover,tr[data-recall-row]:hover,table.list-table tbody tr:has(.row-anchor,td:first-child a[href]):hover,table.list-table tbody tr:has(.row-anchor,td:first-child a[href]):focus-within,.panel tbody tr:hover{background:var(--surface-soft)}
tr[data-open]:focus-visible{outline:2px solid var(--focus);outline-offset:-2px}
tfoot td{border-bottom:0;border-top:1px solid var(--line);color:var(--ink-soft);font-size:13px;padding-top:12px}
.table-footer,.billing-table-footer{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px;padding:14px 24px;border-top:1px solid var(--line);font-size:13px;color:var(--muted)}
.poe-items-table th,.poe-items-table td{padding:10px 6px;vertical-align:top}
.poe-items-table th{padding-top:0;padding-bottom:8px}
.poe-items-table input,.poe-items-table select,.poe-items-table .select-trigger{min-height:38px;font-size:15.5px;padding:8px}

/* Entry lists (.entry-list): a short set of records read one at a time, not compared down a column: the supplier's
   invoice and payment stages of an order, its documents, its supporting files, its costs, a directory. An entry is a state
   mark, two lines (the name, one qualifier) and an optional figure (right, tabular). Tones on the entry: .ok (on record),
   .warn (needs attention), .late (overdue, red), none (waiting).
   ONE RIGHT EDGE: figures end at the card's edge, under the header's own right edge. There is no column of icon buttons:
   an entry that can be edited IS the control. Its name is a button.entry-open (or a.entry-open) stretched over the row
   (.entry.opens tints on hover, Tab reaches it, the title says what opens) and no entry carries a pencil. A stored file
   opens from the small page icon beside the name (a.entry-file, FWDialog.fileLink), only on an entry that has a file. A
   button an entry still needs (Record payment, Restore, Match to a stage) sits in .entry-actions, above the stretched name.
   ONE WEIGHT, AT THE READING SIZE (owner, 2026-10-02, built on the Shipment tab): every name is 15.5px at 600 in ink, every
   small line 14px ink-soft, every figure 16px at 600 in ink (the due figure 22px); nothing in a list is a bold underlined link.
   A sub line (.entry.sub), a reversed line (.entry.void) and a set-aside row (.entry.off) keep regular weight. Money paid out
   is ink, never green: the check mark says it was paid.
   QUIET MARKS: the state mark is a plain icon in a narrow slot (check on record, clock waiting, alert needs attention, in
   the tone's colour). Only .entry.due, the entry that needs action now, is a tinted box with a tile: its figure is a step
   larger, it carries the page's primary button and nothing else on the right, so what it will come to in CAD joins its
   status line (.entry-about, quiet). .calm when the step is simply next, not late.
   .entry.total closes a list: a full rule above it (also straight after the tinted block); with a mark of its own its
   label lines up with the names (payments: .ok a filled check once paid in full, .part the rail's half-filled ring while
   "Sent so far"), without one it is indented to them. A figure keeps its qualifier under it, small
   and quiet (a payment's CAD under its USD amount). .entry-figure.quiet is a date at the right edge (a document).
   .entry.lead has the larger figure without the tint (landed cost per unit); .entry.wrap lets the qualifier run to a second
   line. .entry.sub is a line under an entry (one wire of a stage paid in several). .entry-list.cols is two columns once
   the workspace is wide (file names only: nothing on the right to float mid-card); .entry-list.plain has no marks (the
   products under a landed cost have no state; an order's items are a .list-table, see purchase.css). .entry-note is one quiet line about what is not in the list; .entry-foot is the line that
   adds to it. Anything compared down a column stays a .list-table.
   Only this sheet styles entries (scripts/check-entries.mjs). */
.entry-list{display:grid;grid-template-columns:minmax(0,1fr);column-gap:40px;margin:0;padding:0;list-style:none}
/* An open row menu must sit above later row stacking contexts, including their buttons. */
.entry:has(.action-menu[open]){z-index:1}
.entry{--mark:22px;position:relative;z-index:0;display:flex;align-items:center;gap:12px;min-width:0;padding:11px 0;border-top:1px solid var(--line-soft)}
.dash-panel .entry{--mark:33px}
.entry.due{--mark:36px}
.entry-list>.entry:first-child{border-top:0;padding-top:0}
.entry-icon{display:grid;place-items:center;flex:none;width:22px;height:22px;color:var(--faint)}
.entry[hidden]{display:none}
.dash-panel .entry-icon{width:33px;height:33px;border-radius:10px;background:var(--green-tint);color:var(--green-ink)}
.dash-panel .entry.warn .entry-icon{background:var(--amber-tint);color:var(--amber-ink)}
.dash-panel .entry.late .entry-icon{background:var(--red-tint);color:var(--red-ink)}
.entry-icon svg{width:18px;height:18px}
.entry.ok .entry-icon{color:var(--green)}
.entry.ok .entry-icon svg{stroke-width:2.3}
.entry.warn .entry-icon{color:var(--amber-ink)}
.entry.late .entry-icon{color:var(--red-ink)}
.entry.due .entry-icon{width:36px;height:36px;border-radius:10px;background:var(--amber-tint);color:var(--amber-ink)}
.entry-text{flex:1;min-width:0;font-size:15.5px;line-height:1.4;color:var(--ink)}
.entry-text>*{display:block;overflow-wrap:anywhere}
.entry-text small,.entry-figure small{font-size:14px;color:var(--ink-soft)}
.entry-text a{color:var(--ink);text-decoration:none;text-underline-offset:3px}
.entry-text a:hover{text-decoration:underline}
.entry-name{display:flex;align-items:flex-start;gap:4px;min-width:0;overflow:visible;font-weight:600;color:var(--ink)}
.entry-name>span:first-child{min-width:0}
.entry-open{display:block;min-width:0;max-width:100%;padding:0;border:0;border-radius:0;background:none;font:inherit;line-height:inherit;color:var(--ink);text-align:left;cursor:pointer;overflow-wrap:anywhere}
.entry-text a.entry-open:hover{text-decoration:none}
.entry-open::after{content:'';position:absolute;inset:0 -12px;border-radius:10px}
.entry-open:focus-visible{outline:0}
.entry-open:focus-visible::after{outline:2px solid var(--focus);outline-offset:-1px}
.entry.opens::before{content:'';position:absolute;z-index:-1;inset:1px -12px;border-radius:10px;background:transparent;transition:background .12s}
.entry.opens:hover::before{background:var(--surface-soft)}
/* The first row has no rule and no top padding; one that opens keeps its padding (pulled back by the same margin) so its
   hover tint has the same air above the name as below the last line, like every other row. */
.entry-list>.entry.opens:first-child{padding-top:11px;margin-top:-11px}
.entry.opens .entry-actions,.entry.opens .entry-file{position:relative;z-index:1}
.entry.due.opens::before,.entry.due .entry-open::after{inset:0}
/* The page icon never makes its line taller than the name's own line, so a row with a file is as tall as one without. */
.entry-file{display:inline-grid;place-items:center;flex:none;width:24px;height:22px;margin:-1px 0;border-radius:6px;color:var(--muted)}
.entry-file svg{width:15px;height:15px}
/* The same mark beside a name in the container cost's breakdown, a row that opens its file (purchase.css .lc-row; owner, 2026-10-03). */
.lc-cost .lc-split .k .entry-file{width:20px;height:18px;margin:0 0 0 4px;vertical-align:-3px}
.entry.off .entry-text{color:var(--muted)}
.entry-figure{flex:none;text-align:right;font-size:16px;line-height:1.4;font-variant-numeric:tabular-nums;white-space:nowrap}
.entry-figure b{font-weight:600;color:var(--ink)}
.entry-figure small{display:block}
.entry-figure.quiet{font-size:14px;color:var(--ink-soft)}
/* A checklist (.entry-list.checklist under an .entry-head label): the set a record must have, every row always present in
   one order. On file: the check, the page icon, the date. .entry.missing: an empty ring and one Attach button, with no second
   line until the goods have shipped, then "Missing" in amber (.late; owner, 2026-10-02: the ring says the state once).
   .entry.off: a dash, "Not needed", Undo. No row prints an uploaded file's name. */
.entry-head{margin:16px 0 2px;font-size:12px;line-height:1.4;letter-spacing:.3px;text-transform:uppercase;color:var(--ink-soft)}
.poe-card-head+.entry-head{margin-top:0}
.entry-list.checklist>.entry{padding:9px 0}
/* .entry-list.devices: where an account is signed in (Your account, 2026-10-07): a tile per kind of device, the current one green, the two
   facts each kept whole; on a narrow page the facts take a line each and Sign out goes under them. */
.entry-list.devices>.entry{--mark:38px;gap:14px;padding:14px 0}
.entry-list.devices .entry-icon{width:38px;height:38px;border-radius:10px;background:var(--surface-soft);border:1px solid var(--line-soft);color:var(--ink-soft)}
.entry-list.devices .entry-icon svg{width:20px;height:20px;stroke-width:1.7}
.entry-list.devices>.entry.current .entry-icon{background:var(--green-tint);border-color:var(--green-line);color:var(--green-dark)}
.entry-list.devices .entry-name{flex-wrap:wrap;align-items:center;gap:4px 8px}
.entry-list.devices .entry-text small{margin-top:1px}
@container workspace (max-width:560px){.entry-list.devices>.entry{flex-wrap:wrap}.entry-list.devices .entry-text{flex-basis:calc(100% - 52px)}.entry-list.devices>.entry>.button{margin-left:52px}.entry-list.devices .entry-text small .sep{display:none}.entry-list.devices .entry-text small .nw{display:block}}
.entry-list.checklist>.entry.opens:first-child{padding-top:9px;margin-top:-9px}
.entry-head+.entry-list.checklist>.entry:first-child,.entry-head+.entry-list.checklist>.entry.opens:first-child{padding-top:9px;margin-top:0}
/* Photos of a record (.photo-grid under an .entry-head): square thumbnails, each a button that opens the photo with its
   actions in the shared viewer; the last tile (.photo-add) adds more. The section is drawn only once there are photos (owner,
   2026-10-02): with none, "Add photos" is a text button in the card's .entry-foot, never an empty dashed tile. */
.photo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(92px,1fr));gap:8px;margin-top:8px}
.photo{display:block;aspect-ratio:1;padding:0;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:#eef2ea;cursor:pointer;transition:border-color .12s,box-shadow .12s}
.photo:hover{border-color:#aab99e;box-shadow:0 1px 4px #1a2b1c1f}
.photo img{display:block;width:100%;height:100%;object-fit:cover}
.photo-add{display:grid;place-items:center;align-content:center;gap:4px;aspect-ratio:1;border:1px dashed #ccd3c5;border-radius:10px;background:var(--surface-soft);color:var(--ink-soft);font-size:12.5px;line-height:1.3}
.photo-add:hover{background:#f0f5eb;border-color:#aab99e;color:var(--ink)}
.photo-add svg{width:18px;height:18px}
.entry.missing .entry-icon{width:18px;height:18px;margin:0 2px;border:2px solid #b7c0ae;border-radius:50%}
/* The Bills card of the Storage bills page (review B3/B5/E5, 2026-09-29): the month's bill first and the others under a quiet
   heading (.entry-group); a bill for a month still running has a quiet mark (.entry.running); a bill's figure carries its tone
   (green when the invoice matches the count, amber when it is over); a month with stock and no bill is named in red. */
.entry-list .entry-group{display:block;padding:14px 0 4px;font-size:12px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
.entry-list .entry.running .entry-icon{color:var(--muted)}
.entry-list .entry.warn .entry-figure b,.entry-list .entry.warn .entry-figure small{color:var(--amber-ink)}
.entry-list .entry.missing.shown .entry-text>span:first-child{color:var(--red-ink);font-weight:600}
.entry.missing.late .entry-icon{border-color:#c9ab5c}
.entry.missing.late .entry-text small{color:var(--amber-ink)}
.entry.off .entry-icon::before{content:'';width:10px;height:2px;border-radius:1px;background:var(--faint)}
.entry-actions{display:flex;align-items:center;gap:2px;flex:none;justify-content:flex-end}
/* Two buttons of one row stand apart (at 2px Dispatch and Release touched). */
.entry-actions>.button+.button{margin-left:6px}
.entry-actions:empty{display:none}
.entry-actions .text-btn{margin:0 0 0 6px}
.entry.sub{align-items:flex-start;padding:0 0 10px 34px;border-top:0;font-size:13px}
.entry.sub .entry-text,.entry.sub .entry-figure{font-size:14px;color:var(--muted)}
.entry.sub .entry-name,.entry.void .entry-name,.entry.off .entry-name{font-weight:400;color:inherit}
/* An entry set aside and kept on the record (a reversed payment): quiet, its figure struck through because it counts nowhere. */
.entry.void .entry-text,.entry.void .entry-figure{color:var(--muted)}
.entry.void .entry-figure b{font-weight:400;text-decoration:line-through}
.entry-list>.entry.total{margin-top:6px;padding-top:14px;border-top:1px solid var(--line)}
.entry.total .entry-text{padding-left:34px;color:var(--ink-soft)}
.entry.total .entry-icon+.entry-text{padding-left:0;color:var(--ink)}
.entry.total.ok .entry-icon{border-radius:50%;background:var(--green);color:#fff}
.entry.total.ok .entry-icon svg{width:13px;height:13px;stroke-width:3}
/* Part way there ("Sent so far"): the half-filled ring the payment rail uses for a part-paid step, not a stray clock. */
.entry.total.part .entry-icon{border:2px solid var(--green);border-radius:50%;background:linear-gradient(90deg,var(--green) 50%,var(--surface) 50%)}
.entry-list.plain .entry.total .entry-text{padding-left:0}
.entry.due{margin:8px 0;padding:14px 16px;border:1px solid var(--amber-line);border-radius:10px;background:var(--amber-soft)}
.entry-list>.entry.due:first-child{margin-top:0;padding-top:14px}
.entry.due+.entry{border-top:0}
/* The closing line keeps its full rule and its air even straight after the tinted block. */
.entry-list>.entry.due+.entry.total{margin-top:14px;border-top:1px solid var(--line)}
.entry.due.calm{border-color:#e6ebe3;background:var(--surface-soft)}
.entry.due.calm .entry-icon{background:#eef2ea;color:var(--muted)}
.entry.due.calm .entry-text small{color:var(--muted)}
.entry.due .entry-text small{color:var(--amber-ink)}
.entry.due .entry-figure b,.entry.lead .entry-figure b{font-size:22px;letter-spacing:-.3px;line-height:1.25}
.entry.due .entry-actions{margin-left:18px}
.entry.due .entry-text small .entry-about{color:var(--muted)}
/* Inside an entry: .progress is how much of a quantity has arrived (under the figure). */
.progress{display:block;width:100%;min-width:64px;max-width:140px;height:6px;margin:8px 0 0 auto;border-radius:8px;background:#e9eee3;overflow:hidden}
.progress i{display:block;height:100%;border-radius:8px;background:#609b4e}
/* The icon on the head of a section that is not an entry (.expect-head, the Receiving tab's Still expected) is the same tile. The
   Receiving tab's list of what had arrived (.entry-list.recv) and its "Where it came from" checklist (.entry-list.trace) were retired on
   2026-10-04: what arrived is Against the order (a list table) and the Deliveries card (purchase.css), the trace is the Shipment tab's. */
.expect-head .entry-icon{flex:none;display:grid;place-items:center;width:36px;height:36px;margin:0;border-radius:9px;background:#eef2ea;color:var(--ink-soft)}
.expect-head .entry-icon svg{width:18px;height:18px}
/* A recall's stop beside a lot named away from its page (a Receiving tab delivery line, the reversal window; owner, 2026-10-04): a red
   mark that opens the recall. Red is the recall's colour alone; amber says waiting or late. */
.rx-mark{display:inline-flex;align-items:center;gap:6px;padding:2px 9px;border-radius:7px;background:var(--red-tint);color:var(--red-ink);box-shadow:inset 0 0 0 1px var(--red-line);font-size:13.5px;font-weight:600;line-height:1.4;white-space:nowrap;text-decoration:none}
.rx-mark svg{width:14px;height:14px}
a.rx-mark:hover{color:var(--red-ink);text-decoration:underline}
.entry-note{display:flex;align-items:flex-start;gap:8px;padding:11px 0;border-top:1px solid var(--line-soft);font-size:14.5px;line-height:1.5;color:var(--ink-soft)}
/* Alone in its card (nothing on record yet) a note has no list above it to be ruled off from. */
.entry-note:first-child,.poe-card-head+.entry-note,.panel-top+.entry-note{padding-top:2px;border-top:0}
.entry-note [data-icon]{flex:none;margin-top:2px;color:var(--muted)}
.entry-note>span:last-child{flex:1;min-width:0}
.entry-note svg{width:16px;height:16px}
.entry-note.warn b,.entry-note.warn [data-icon]{color:var(--amber-ink)}
/* .entry-foot closes a card under a quiet rule with what adds to its list: text buttons (Add another document, Add photos) or
   the card's one small button (Add charge, Add evidence). The row that typed a document's kind beside Choose file is retired
   (owner, 2026-10-02; check-entries keeps its class out): a document is attached from its own row or through the Add document window. */
.entry-foot{display:flex;align-items:center;gap:8px 22px;flex-wrap:wrap;margin-top:2px;padding-top:14px;border-top:1px solid var(--line-soft)}
/* The Delivery card (freight.js; owner, 2026-10-03): on an invoice, what the customer was charged for delivery beside what the delivery
   cost, a row each, the figure at the right; a cost not recorded yet is amber. */
.dl-pair{display:grid;gap:8px;margin-bottom:12px}
.dl-fig{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:12px;align-items:baseline;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--surface-soft)}
.dl-fig>span{grid-column:1;grid-row:1;font-size:12.5px;font-weight:700;line-height:1.4;letter-spacing:.5px;text-transform:uppercase;color:var(--muted)}
.dl-fig>b{grid-column:2;grid-row:1;font-size:17px;font-weight:600;color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.dl-fig>b.none{color:var(--ink-soft);font-weight:500}
.dl-fig>small{grid-column:1/-1;font-size:14px;color:var(--ink-soft)}
.entry-foot .text-btn{font-size:14.5px}
.entry-list:empty+.entry-note,.entry-list:empty+.entry-foot{border-top:0;padding-top:0}
.entry-drop{outline:2px dashed var(--focus);outline-offset:-6px}
@container workspace (min-width:1100px){.entry-list.cols{grid-template-columns:repeat(2,minmax(0,1fr))}.entry-list.cols>.entry:nth-child(2){border-top:0;padding-top:0}}
/* On a phone a figure goes under the text and a due entry's button under both, full width: so a due entry wraps whether
   or not it carries a figure (its button row takes a whole line, which a row that may not wrap cannot give it). Under the
   text the figure's qualifier wraps too ("Closed short · 10 cases not coming · credit note CN-G" is wider than a phone). */
@container workspace (max-width:560px){.entry.figured,.entry.due{flex-wrap:wrap}.entry.figured .entry-text{flex:1 1 calc(100% - var(--mark) - 12px)}.entry.figured .entry-figure{flex:1;min-width:0;white-space:normal;overflow-wrap:anywhere;margin-left:calc(var(--mark) + 12px);text-align:left}.entry.figured .entry-figure small{white-space:normal}.entry.figured .entry-figure.quiet{flex:none;margin-left:0}.entry.figured .progress{margin-left:0}.entry-list.plain .entry.figured .entry-text{flex-basis:100%}.entry-list.plain .entry.figured .entry-figure{margin-left:0}.entry.due .entry-actions{flex-basis:100%;margin:4px 0 0}.entry.due .entry-actions .button{width:100%}.entry.figured .entry-actions{flex:0 1 calc(100% - var(--mark) - 12px);justify-content:flex-start;margin:6px 0 0 calc(var(--mark) + 12px)}.entry.sub .entry-figure{margin-left:0}}

/* A meter: how many of a short set are on record, one bar per item (documents on file). */
.meter{display:inline-flex;gap:3px;vertical-align:middle}
.meter i{width:14px;height:4px;border-radius:2px;background:var(--line)}
.meter i.on{background:var(--green)}

/* A detail page with a side column: the main column is fluid, the side column a fixed --side-column, and they stack below
   1040px of workspace. The side column holds what is glanced at (transit, history, the landed-cost summary). */
.with-side{display:grid;grid-template-columns:minmax(0,1fr);gap:20px;min-width:0;align-items:start}
/* A side column that carries the stock behind a document (.stock-first) puts it first when the columns stack (owner, 2026-09-29). */
@container workspace (max-width:1039px){.with-side>aside.stock-first{display:flex;flex-direction:column-reverse}}
.with-side>*{display:grid;gap:20px;align-content:start;min-width:0}
@container workspace (min-width:1040px){.with-side{grid-template-columns:minmax(0,1fr) var(--side-column)}}
/* The Shipment tab's side column (Transit, History; owner, 2026-10-02), the Costs tab's (Charges, Claims; owner, 2026-10-03) and the
   Receiving tab's (the supplier's claims beside the deliveries; owner, 2026-10-04) take what the main column can spare: the main keeps
   680px (the payments card's due row on one line, the cost breakdown's four columns, a delivery line's facts), and the side grows from
   --side-column to 460px. The other pages keep --side-column. */
@container workspace (min-width:1040px){.with-side.ship-split,.with-side.cost-split,.with-side.recv-split{grid-template-columns:minmax(0,1fr) clamp(var(--side-column),calc(100% - 700px),460px)}}
/* The Storage bills page keeps its count whole (review D5, 2026-09-29): its side column waits until the count table fits beside it. */
@container workspace (min-width:1040px){#storage-view .with-side{grid-template-columns:minmax(0,1fr)}}
@container workspace (min-width:1100px){#storage-view .with-side{grid-template-columns:minmax(0,1fr) var(--side-column)}}
/* A row of cards in the main column (.card-row): the wide card, then a pair (.card-pair). Side by side (5 to 4) once the
   workspace is wide enough for both to read without wrapping (1640px), the wide card over the pair below that, one column on a phone; the two cards of a pair are always one height. */
.card-row{display:grid;grid-template-columns:minmax(0,1fr);gap:20px;align-items:start;min-width:0}
.card-pair{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px;align-items:stretch;min-width:0}
@container workspace (min-width:1640px){.card-row{grid-template-columns:minmax(0,5fr) minmax(0,4fr)}}
@container workspace (max-width:640px){.card-pair{grid-template-columns:minmax(0,1fr)}}

/* Fact strips (.lc-summary > .lc-facts > .lc-fact): the figures that open a page, each a label, a value and one line
   under it: the order page's summary (four cells, with the payment rail beneath, see purchase.css) and the strips above the
   purchase-order and invoice lists (.three: three equal cells). .lead is the large figure; a figure in two currencies is
   one line per currency (.currency-total); .due reads amber (money to pay now), .late red (money owed to us past its date).
   The strip folds to two cells a row, then one; .three folds straight to one. */
.lc-summary{padding:0;margin-bottom:24px;background:transparent;border:0;box-shadow:none}
/* A supplier's page: the strip, their orders across the page (the list's own table), then payments beside the Account card. */
.supplier-page>.shipment-panel{margin-bottom:24px}
.lc-facts{display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1.4fr) repeat(2,minmax(0,1fr));gap:14px}
.lc-fact{display:flex;flex-direction:column;gap:4px;min-width:0;padding:18px 20px;border:1px solid var(--line);border-top:3px solid var(--lime);border-radius:13px;background:var(--surface);box-shadow:0 2px 8px #233b2706}
.lc-fact.late{border-top-color:#c8825a;background:#fffaf4}
.lc-fact.due{border-top-color:var(--green)}
.lc-fact:first-child{border-left:1px solid var(--line)}
.lc-fact>span{font-size:12px;font-weight:700;letter-spacing:.8px;text-transform:uppercase;color:var(--muted);line-height:1.3}
.lc-fact>strong{font-size:15px;line-height:1.35;color:var(--ink);font-variant-numeric:tabular-nums;display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 7px;max-width:100%}
.lc-v{max-width:100%;overflow:hidden}
.lc-fact.lead>strong{font-size:26px;font-weight:650;letter-spacing:-.6px;line-height:1.25}
.lc-fact>strong.lc-empty{color:var(--muted)}
.lc-fact.lead>strong.lc-empty{font-size:15px;line-height:1.35;letter-spacing:0;padding-top:4px}
.lc-fact small{font-size:13.5px;line-height:1.45;color:var(--ink-soft);letter-spacing:0;white-space:normal}
.lc-fact.warn small{color:var(--amber-ink)}
.lc-fact .currency-total{flex-basis:100%}
.lc-fact.due>strong,.lc-fact.due small{color:var(--amber-ink)}
.lc-fact.late>strong,.lc-fact.late small{color:var(--red)}
/* The month's bill leads the Storage bills strip (review E1, 2026-09-29): green when the invoice matches the count, amber when it
   is over it, quiet while the month runs; its second line is read at the reading size with the count in weight. */
.lc-fact.match{border-top-color:var(--green)}
.lc-fact.match>strong{color:var(--green-ink)}
.lc-fact.over{border-top-color:var(--amber-edge);background:var(--amber-soft)}
.lc-fact.over>strong,.lc-fact.over small .warn{color:var(--amber-ink)}
.lc-fact.open{border-top-color:#b7c2b4}
.lc-fact.lead small{font-size:14.5px;line-height:1.45;color:var(--ink-soft)}
.lc-fact.lead small b{font-weight:600;color:var(--ink)}
@container workspace (max-width:1000px){.lc-facts{grid-template-columns:repeat(2,minmax(0,1fr))}.lc-facts .lc-fact:nth-child(odd){border-left:1px solid var(--line)}}
@container workspace (max-width:560px){.lc-facts{grid-template-columns:minmax(0,1fr);gap:14px}.lc-facts .lc-fact{border-left:1px solid var(--line)}}
@container workspace (min-width:721px){.lc-facts.two{grid-template-columns:repeat(2,minmax(0,1fr))}.lc-facts.three{grid-template-columns:repeat(3,minmax(0,1fr))}.lc-facts.three .lc-fact:nth-child(3){padding-left:20px;border-left:1px solid var(--line)}}
@container workspace (max-width:720px){.lc-facts.three{grid-template-columns:minmax(0,1fr);gap:14px}.lc-facts.three .lc-fact{border-left:1px solid var(--line)}}

/* The one next step of a row (owner, 2026-09-29, the sales workflow review; journey-model quoteNext / orderNext): a small button at
   the right of the wait cell, as the Overview's entries carry theirs; the wait keeps the width and no button wraps a word. Stacked
   on a narrow page the buttons sit under the wait. */
.list-table td.next{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.list-table td.next>.row-wait{flex:1;min-width:0}
.list-table td.next>.row-next{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:6px;padding-top:1px}
.list-table td.next .button.small,.list-table td.next .text-btn.small{white-space:nowrap}
@container workspace (max-width:820px){.list-table td.next{display:block}.list-table td.next>.row-next{flex-direction:row;justify-content:flex-start;margin-top:10px}}
/* The four steps of a sale (owner, 2026-09-29; journey-model): one line under the head of the quote, the order and the invoice.
   What is done has a check and a link, what is now is in colour, what is to come is quiet, an overdue step red. Four steps, never five. */
.journey{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:0 0 var(--section-gap);padding:14px 18px;border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);list-style:none}
.journey li{display:grid;grid-template-columns:24px minmax(0,1fr);gap:2px 10px;align-items:start;min-width:0}
.journey .jmark{grid-row:span 2;display:grid;place-items:center;width:24px;height:24px;border-radius:50%;background:var(--line-soft);color:var(--muted)}
.journey .jmark svg{width:14px;height:14px}
.journey li.done .jmark{background:var(--green-tint);color:var(--green-ink)}
.journey li.now .jmark{background:var(--green);color:#fff}
.journey .jname{font-size:15.5px;font-weight:600;line-height:1.35;color:var(--ink)}
.journey .jname a{color:inherit}
.journey li.next .jname,.journey li.skip .jname{font-weight:500;color:var(--muted)}
.journey li.now .jname{color:var(--green-ink)}
.journey .jsub{font-size:14px;line-height:1.4;color:var(--ink-soft)}
.journey li.next .jsub,.journey li.skip .jsub{color:var(--muted)}
.journey li.late .jsub,.journey li.late .jname{color:var(--red-ink)}
@container workspace (max-width:820px){.journey{grid-template-columns:repeat(2,minmax(0,1fr))}}
@container workspace (max-width:480px){.journey{grid-template-columns:minmax(0,1fr)}}
/* Where an order came from, first on its page on the day it was accepted (owner, 2026-09-29). */
.from-line{margin:0 0 14px;font-size:14.5px;line-height:1.45;color:var(--ink-soft)}
.from-line a{color:var(--green)}
/* A tile that opens a page is a link (owner, 2026-09-29: Sales in progress opens Sales orders, Quotes waiting its Quotes tab). */
a.lc-fact{text-decoration:none;color:inherit;cursor:pointer}
a.lc-fact:hover{border-color:var(--green)}
a.lc-fact:hover>span{color:var(--green-ink)}
/* What a row is waiting on (.row-wait): an icon from FWLayout and one to three lines, the first the fact in weight, the
   next its qualifiers in ink (a .quiet qualifier is muted whatever the tone). The tone is on the fact and its mark only:
   .warn amber (needs the owner), .late red (overdue), .done (a green check), .none (nothing is awaited: a muted dash, no
   mark), none (waiting). It says what is STILL TO COME, never what has happened. The purchase-order list and the invoice
   list both lead their rows with it, and sort by it; on the purchase-order list the row that needs the owner (tr.needs)
   is the tinted block, the same amber as the due entry on the Shipment tab (.entry.due). The invoice list does not tint:
   an overdue invoice is its common case, and a wall of amber says nothing. */
.row-wait{display:flex;align-items:flex-start;gap:10px;min-width:0}
.row-wait>div{min-width:0}
.row-wait-icon{flex:none;margin-top:1px;color:var(--muted)}
.row-wait-icon svg{width:19px;height:19px}
.list-table .row-wait small{white-space:normal}
.list-table .row-wait small.quiet{color:var(--muted)}
.row-wait.warn strong,.row-wait.warn .row-wait-icon,.row-wait small.warn{color:var(--amber-ink)}
.row-wait.late strong,.row-wait.late .row-wait-icon{color:var(--red)}
.row-wait.done .row-wait-icon{color:var(--green-ink)}
.list-table .row-wait.none strong{font-weight:400;color:var(--muted)}
.list-table tr.needs td{background:var(--amber-soft);border-bottom-color:var(--amber-line)}
/* A timeline (.lc-timeline): what happened over when, newest first: an order's history, the Overview's recent activity, the
   Settings audit trail (there a li.day names each day). The older entries of a short one open on demand (.lc-timeline-more). */
.lc-timeline{margin:0;padding:0;list-style:none;font-size:15px;line-height:1.45}
.lc-timeline li{display:grid;gap:1px;padding:9px 0;border-bottom:1px solid var(--line-soft)}
.lc-timeline li:first-child{padding-top:0}
.lc-timeline li:last-child{border-bottom:0}
.lc-timeline small{font-size:13.5px;color:var(--ink-soft);font-variant-numeric:tabular-nums}
.lc-timeline li.day{padding:16px 0 6px;border-bottom:1px solid var(--line);font-size:12.5px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;color:var(--muted)}
.lc-timeline li.day:first-child{padding-top:0}
.lc-timeline-more{margin-top:10px}
/* An order's History line (.ev, purchasing.js timelineCard; owner, 2026-10-02): what happened in weight, the time it was recorded at
   the right, its details under it, who recorded it last. */
.lc-timeline li.ev{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:16px;align-items:baseline}
.lc-timeline .ev-what{font-weight:600;color:var(--ink)}
.lc-timeline .ev-what .text-btn{font:inherit;color:inherit}
.lc-timeline .ev-when{grid-column:2;grid-row:1;white-space:nowrap}
.lc-timeline .ev-more{grid-column:1/-1;font-size:14px;color:var(--ink-soft)}
.lc-timeline .ev-who{grid-column:1/-1;color:var(--muted)}
/* A list whose first cell names the record in three lines (number and chip, who, dates) and whose money cell carries a bar. */
.list-table td:first-child .row-anchor+.status,.list-table td:first-child .row-anchor+.poe-status{margin:0 0 0 8px;vertical-align:2px}
.list-table td:first-child .row-anchor~small:first-of-type{margin-top:4px}
/* The money cell's bar is wide enough to read a quarter on; the line under it is the one place the paid state is said (the
   invoice list: "Nothing paid", what is left to collect, "Paid in full" / "Settled" in green, what is owed back in amber). */
.list-table td.col-num .progress{width:160px;height:6px;margin-top:8px;border-radius:3px}
.list-table td.col-num .progress i{border-radius:3px}
.list-table td.col-num small{margin-top:5px}
.list-table td.col-num small.full{color:var(--green-ink);font-weight:600}
.list-table td.col-num small.owed{color:var(--amber-ink);font-weight:600}

/* Tabs, search and toolbars. */
/* A list's toolbar has room to breathe (owner, 2026-09-29): the tray and the filters on one line with air between them, the tab and its
   count one control, the search wide enough for a name; when the filters drop under the tabs they take the whole line. One rule for
   every list. */
.tabs,.lc-tabs{display:inline-flex;gap:4px;padding:4px;max-width:100%;min-height:var(--control);overflow-x:auto;background:#edf1e7;border:1px solid var(--line);border-radius:11px}
.tabs button,.lc-tabs button{display:inline-flex;align-items:center;gap:7px;min-height:calc(var(--control) - 10px);padding:5px 14px;border:1px solid transparent;border-radius:8px;background:none;box-shadow:none;color:var(--ink-soft);font-size:14px;font-weight:600;line-height:1.3;white-space:nowrap;flex:none}
.tabs button:hover,.lc-tabs button:hover{color:var(--ink);background:#f7faf4;border-color:transparent}
.tabs button.active,.lc-tabs button.active{color:var(--green-ink);background:var(--surface);border-color:#d4dacf;box-shadow:0 1px 3px #1b3a2814}
/* The count on a tab is a quiet figure beside its name (2026-10-05): a tinted chip on the tray's tint vanished. Ink-soft, tabular, green on
   the open tab; the Filters button keeps the chip. */
.tabs .filter-count,.lc-tabs .filter-count{display:inline;min-width:0;height:auto;padding:0;border-radius:0;background:none;color:var(--muted);font-size:13.5px;font-weight:600;line-height:inherit}
.tabs button:hover .filter-count,.lc-tabs button:hover .filter-count{color:var(--ink)}
.tabs button.active .filter-count,.lc-tabs button.active .filter-count{color:var(--green-ink)}
.lc-tabs{margin:0 0 18px}
.search{position:relative;flex:1;min-width:220px;max-width:380px}
.search [data-icon]{position:absolute;left:14px;top:50%;transform:translateY(-50%);color:var(--muted);pointer-events:none}
.search svg{width:16px;height:16px}
.search input{padding-left:40px}
.table-toolbar,.toolbar{display:flex;align-items:center;justify-content:space-between;gap:14px 28px;flex-wrap:wrap;padding:18px 24px;border-bottom:1px solid var(--line)}
/* A toolbar's filters (a company, a month, a warehouse) and its search are ONE row, to the right of the tabs: the row never stacks
   its controls beside the tray (2026-10-05: the company filter sat over the search at a width where both did not fit beside six tabs);
   when it does not fit, the whole row drops under the tabs, left-aligned, the search filling the line. */
.toolbar-filters{display:flex;flex:1 1 auto;flex-wrap:nowrap;align-items:center;justify-content:flex-end;gap:12px}
.toolbar-filters .search{flex:1 1 260px;min-width:220px;max-width:380px}
.toolbar-filters>.select-shell,.toolbar-filters>select{flex:0 0 auto;min-width:190px;width:auto}
@container workspace (max-width:1180px){.toolbar-filters{flex-basis:100%;justify-content:flex-start}.toolbar-filters .search{max-width:none}.toolbar-filters>.select-shell,.toolbar-filters>select{flex:0 0 220px}}
/* A toolbar whose filters are pills (owner, 2026-09-30; the invoice list: "filter buttons, not individual tabs"): one row that wraps, the
   pills at their own widths (the status among them, there is no tab tray), Clear beside them once one is applied, the search at the
   row's right end. */
.toolbar-filters.pills{flex:1 1 100%;flex-wrap:wrap;justify-content:flex-start;gap:10px 8px}
.toolbar-filters.pills>.select-shell{flex:0 0 auto;width:auto;min-width:0}
.toolbar-filters.pills .text-btn{margin-left:4px}
.toolbar-filters.pills .search{margin-left:auto;flex:1 1 240px;max-width:420px}
/* On a phone a list's tabs are one dropdown (owner, 2026-09-29): FWLayout.tabsSelect draws the select and selects.js its shell, in place
   of the tray under 600px; the trigger reads the tab and its count. */
.table-toolbar>.tabs-select,.toolbar>.tabs-select,.table-toolbar>.select-shell:has(>.tabs-select),.toolbar>.select-shell:has(>.tabs-select){display:none}
@media(max-width:600px){.table-toolbar:has(>.select-shell>.tabs-select)>.tabs,.toolbar:has(>.select-shell>.tabs-select)>.tabs{display:none}.table-toolbar>.select-shell:has(>.tabs-select),.toolbar>.select-shell:has(>.tabs-select){display:block}.select-shell:has(>.tabs-select) .select-trigger{font-weight:600;color:var(--green-ink)}}
/* A list row's quiet lines are ink (.list-table td small); a line that warns keeps its colour over that: amber for what is near
   (.warn), the alert red for what is refused or late (.warning-text: "Over limit", "On hold", "All overdue"). */
.list-table td small.warn{color:var(--amber-ink)}
.list-table td small.warning-text{color:var(--red)}
/* The refusal said beside an action a role is not offered (a disabled button in a page head: the server would refuse it). */
.action-note{flex:1 1 260px;max-width:460px;font-size:14.5px;line-height:1.45;color:var(--red)}
.filter-summary{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 24px;border-bottom:1px solid var(--line);font-size:13px;color:var(--muted)}

/* Notices, errors and empty states. */
.form-note,.notice,.poe-note{display:flex;gap:10px;align-items:flex-start;padding:12px 16px;border:1px solid #d5e3c5;border-radius:10px;background:#f3f7ed;color:var(--ink);font-size:14px;line-height:1.55;margin:0 0 16px}
.form-note{display:block}
.dialog-error,.document-error,.poe-error-card{display:block;padding:12px 16px;border:1px solid var(--red-line);border-radius:10px;background:var(--red-tint);color:var(--red-ink);font-size:14px;line-height:1.55;margin:0 0 16px}
.poe-error-card strong{display:block}
.poe-error-card ul{margin:6px 0 0;padding-left:18px}
.poe-error-card li{padding:2px 0}
.empty,.billing-empty{padding:36px 20px;text-align:center;color:var(--muted);font-size:14px;line-height:1.7}
.empty strong,.billing-empty h3{display:block;color:var(--ink);font-size:15px;margin-bottom:4px}
.billing-empty .button{margin-top:14px}

/* Dialogs: one frame for every module, built by public/dialog.js (window.FWDialog); no screen creates its own <dialog>
   and no module sheet styles the frame. A form dialog is a title band with a close button, a body that scrolls on its
   own and a button band. A confirm dialog (.confirm) is a compact card: the question is its heading, then one or two
   muted sentences, then the buttons with no band between; it grows to fit its buttons (480-560px). In the button row the primary action is last (green; red with
   .danger when it destroys something), the safe way out is the plain button before it, and a destructive alternative
   (.aside, "Discard changes") stands alone on the left. Escape and the close button always close; a click outside
   closes a confirm or a read-only sheet. On phones the buttons stack full width with the primary on top.
   `node scripts/check-dialogs.mjs` (in npm run lint) fails on a dialog built anywhere else. */
dialog.dialog{display:none;flex-direction:column;width:min(600px,calc(100% - 32px));max-height:calc(100dvh - 48px);margin:auto;padding:0;border:1px solid #d7e0d0;border-radius:18px;background:var(--surface);color:var(--ink);box-shadow:0 28px 90px #0c2a3540;overflow:hidden}
dialog.dialog[open]{display:flex;transition:opacity .18s ease,transform .18s ease}
@starting-style{dialog.dialog[open]{opacity:0;transform:translateY(10px) scale(.985)}}
dialog.dialog::backdrop{background:#102e2766;backdrop-filter:blur(3px)}
dialog.dialog.wide{width:min(1040px,calc(100% - 40px))}
dialog.dialog.view{width:min(1100px,calc(100% - 40px));height:calc(100dvh - 48px)}
dialog.dialog.confirm{width:fit-content;min-width:min(480px,calc(100% - 32px));max-width:min(560px,calc(100% - 32px))}
.dialog-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex:none;padding:20px 26px;background:#f0f5e9;border-bottom:1px solid #d1ddc8}
.dialog-head h2{font-size:18px}
.dialog-body{flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain;padding:24px}
.dialog-body>p,.dialog-body>form>p{margin:0 0 16px;line-height:1.6}
.dialog-body>p:last-of-type,.dialog-body>form>p:last-of-type{margin-bottom:0}
.dialog-error{margin:16px 0 0}
/* The file viewer (FWDialog.file): the stored PDF or picture fills the body; a picture larger than the frame scrolls. */
.view .dialog-body{display:grid;padding:0;background:var(--surface-soft)}
.view .dialog-error{margin:16px}
.dialog-file{display:block;width:100%;height:100%;border:0}
img.dialog-file{width:auto;height:auto;max-width:100%;margin:auto}
/* On a phone or a touch screen a PDF cannot be shown inside the page: the window offers it in the device's own viewer. */
.dialog-file-link{display:grid;place-items:center;min-height:160px;margin:0;padding:24px}
.dialog-foot{display:flex;justify-content:flex-end;align-items:center;gap:10px;flex-wrap:wrap;flex:none;padding:16px 26px;background:var(--surface-soft);border-top:1px solid #d1ddc8}
.dialog-foot .button{min-width:104px}
.dialog-foot .aside{margin-right:auto}
.confirm .dialog-body{padding:28px 28px 4px}
.confirm .dialog-body>h2{font-size:19px;line-height:1.3;margin:0 0 8px}
.confirm .dialog-body>p,.confirm .dialog-body>form>p{color:var(--muted);font-size:15px;margin-bottom:12px}
.confirm .dialog-body .field{margin-top:16px}
.confirm .dialog-foot{border-top:0;flex-wrap:nowrap;padding:20px 28px 24px}
dialog[aria-busy=true] .dialog-foot .button,dialog[aria-busy=true] .dialog-foot .text-btn{pointer-events:none;opacity:.55}
.saving button[type=submit],.saving .dialog-foot .primary,.poe[aria-busy=true] .button,.poe[aria-busy=true] input,.poe[aria-busy=true] select,.poe[aria-busy=true] textarea,.poe[aria-busy=true] .select-trigger{pointer-events:none;opacity:.55}

/* Toasts. */
.toast,#billing-toast{position:fixed;bottom:24px;left:calc(50% + var(--sidebar-width)/2);transform:translateX(-50%);z-index:100;width:max-content;max-width:calc(100% - 40px);margin:0;padding:12px 20px;border-radius:10px;background:#214f22;color:#fff;font-size:14px;box-shadow:0 10px 30px #183b2433}
#billing-toast{opacity:0;pointer-events:none;transform:translateX(-50%) translateY(20px);transition:opacity .15s,transform .15s}
#billing-toast.visible{opacity:1;transform:translateX(-50%)}

/* Metrics: the summary cards on every list screen. */
.summary{padding:18px 22px}
.summary>strong{display:block;font-size:26px;line-height:1.3;letter-spacing:-.5px;color:var(--ink);margin:6px 0 2px;font-variant-numeric:tabular-nums}
/* A figure in more than one currency is one line per currency (.currency-total), a step smaller so two lines fit the tile. */
.summary:has(.currency-total)>strong{font-size:22px}
.currency-total{display:block}
.currency-total small{font-size:12.5px;color:var(--muted);letter-spacing:0}
.summary>div:last-child{font-size:12.5px;color:var(--muted)}

/* Shipment inventory (owner, 2026-09-22 and 2026-09-28): no tiles; the lots grouped under their product, the product first, whatever
   warehouse they are in. A product with several lots has a heading row (.product-group: tinted, its name, how many lots in how many
   warehouses, its totals per unit, its oldest age; ONLY ITS NAME IS IN WEIGHT) and its lots under it (.in-group: indented, led by their pack in regular weight,
   so product names are the only names in weight). EVERY PRODUCT STARTS ON A GREEN RULE (.product-group, and .product-start on a
   product of one lot), its heading a quiet band; no line runs down the side. Columns: Product, Lot (.lot-no: the number in green,
   never underlined, the link a keyboard reaches; the order or reference), Warehouse (a column of its own while more than one holds
   stock; .one-place drops it), On hand (with the bar), Reserved (the amber line says for whom), Free to sell, In stock for (a chip,
   amber once past its product's own days; set apart from the figures). The table is .compact. THE ROW IS THE CONTROL: a lot's row opens its page (#lot/<id>). The Arriving
   tab is its own table (.arriving-table): a row per order, each product on its own line of .to-come with what is still to come in
   its own unit; the row opens the order's Receiving tab. Widths are on th only. */
.key{width:9px;height:9px;border-radius:3px;display:block}
.arriving-table{min-width:760px}
.shipment-table{min-width:900px}
.shipment-table th:nth-child(1){width:24%}
.shipment-table th:nth-child(2){width:14%}
.shipment-table th:nth-child(3){width:13%}
.shipment-table th:nth-child(4){width:14%}
.shipment-table th:nth-child(5){width:13%}
.shipment-table th:nth-child(6){width:12%}
.shipment-table.one-place{min-width:760px}
.shipment-table.one-place th:nth-child(3),.shipment-table.one-place td:nth-child(3){display:none}
.shipment-table.one-place th:nth-child(1){width:30%}
.shipment-table.one-place th:nth-child(2){width:16%}
.shipment-table.one-place th:nth-child(4){width:15%}
.shipment-table.one-place th:nth-child(5){width:15%}
.shipment-table.one-place th:nth-child(6){width:12%}
.shipment-table th:last-child,.shipment-table td:last-child{padding-left:32px}
/* The product's name is the one prominent thing of its row (owner, 2026-09-28): in weight, a size above; what stands beside it in a
   heading row (how many lots, where, the totals) is regular. */
.shipment-table td:first-child strong{font-size:17px;font-weight:700}
.shipment-table tr.product-group td{font-size:16px;line-height:1.4;color:var(--ink)}
.shipment-table tr.product-group .sum{display:block;font-variant-numeric:tabular-nums}
.shipment-table td:nth-child(3){font-size:15px;line-height:1.4;color:var(--ink)}
.arriving-table th:nth-child(1){width:26%}
.arriving-table th:nth-child(2){width:44%}
.arriving-table th:nth-child(3){width:20%}
.lot-no{color:var(--green-ink);font-size:15.5px;font-weight:600;text-decoration:none;font-variant-numeric:tabular-nums}
.lot-no:hover{color:var(--green-ink);text-decoration:none}
/* A lot's number is one word: in the table it is never broken at a hyphen (its column grows); stacked, it wraps where it must. */
.shipment-table .lot-no{white-space:nowrap}
.shipment-table td small.warn{color:var(--amber-ink)}
.shipment-table td.col-num small{white-space:normal}
.shipment-table td.col-status small{margin-top:6px}
.shipment-table tr.product-group{cursor:default}
.shipment-table tr.product-group td{background:var(--surface-soft);border-bottom:1px solid var(--line);padding-top:10px;padding-bottom:10px}
.shipment-table tr.product-group td,.shipment-table tr.product-start td{border-top:2px solid var(--green-line)}
.shipment-table tbody tr:first-child td{border-top:0}
.shipment-table tr.product-group td small{margin-top:0}
.shipment-table tr.in-group td:first-child{padding-left:48px}
.shipment-table tr.in-group td:first-child strong{font-size:15px;font-weight:400}
.shipment-table tr.group-end td{border-bottom:1px solid var(--green-line)}
.to-come{display:grid;gap:10px;margin:0;padding:0;list-style:none}
.to-come li{display:flex;align-items:baseline;justify-content:space-between;gap:16px}
.to-come b{font-size:15.5px;font-weight:600}
.to-come small{display:block;margin-top:2px;font-size:14px;color:var(--ink-soft)}
.to-come .n{white-space:nowrap;font-variant-numeric:tabular-nums}
.list-table td:not(.col-num) .progress{margin-left:0}
dt{color:var(--ink-soft);flex-shrink:0}
dd{margin:0;text-align:right;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}
@container workspace (max-width:820px){.arriving-table td:nth-child(2){grid-column:1/-1}.shipment-table tr.product-group{background:var(--surface-soft)}.shipment-table tr.product-group,.shipment-table tr.product-start{border-top:2px solid var(--green-line)}.shipment-table tr.product-group td,.shipment-table tr.product-start td{background:none;border:0}.shipment-table tr.product-group td{padding:0}.shipment-table tr.in-group{padding-left:40px}.shipment-table tr.in-group td:first-child{padding-left:0}.shipment-table tr.group-end{border-bottom:1px solid var(--green-line)}.shipment-table tr.group-end td{border-bottom:0}.shipment-table .lot-no{white-space:normal;overflow-wrap:anywhere}}
/* Stacked, a lot's six facts fill whole lines: three to a line on a tablet, two on a phone, so none is left alone on a line of its own. */
@container workspace (max-width:820px){table.shipment-table tbody tr[data-lot-row],table.shipment-table tbody tr.product-group{display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}}
@container workspace (max-width:560px){table.shipment-table tbody tr[data-lot-row],table.shipment-table tbody tr.product-group{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}}
/* The lot's page (#lot-view, app.js renderLot; reviewed 2026-09-29): the frame's head with the way back, a strip (on hand, free to
   sell, in stock for; its second lines are read, so they are the reading size and wrap between their facts), then .with-side with
   the STOCK FIRST when the columns stack: a recall's stop (.lot-stop), Where it went, Reserved for customers, Claims and the whole
   History in the main column; Where it came from (label over value: .lc-dl.read.over) and the cost of the lot in the side column.
   Every card is a .poe-card; the history is .lot-history (purchase.css; the lot page's alone since 2026-10-04), the answer the Costs tab's .lc-answer
   + .lc-split (per unit only: the totals are the order's). Reading rule: ink at 15px, names and figures at 600 and 15.5px, second
   lines ink at 14px, small capital labels. */
.lc-fact small.wrap{white-space:normal}
.lot-page .poe-card-head{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 10px}
.lot-page .poe-card-head h2{margin:0}
.lot-page .poe-card-head .tag{margin-left:auto}
.lot-page .poe-card-head .lc-count{font-size:14px;color:var(--ink-soft)}
.lot-page .lot-history{padding:0}
.lot-page .lot-history li{padding:11px 0;font-size:15px}
.lot-page .lot-history li:first-child{padding-top:2px}
/* A link in the History reads as a link (it was ink with no underline: invoice and transfer numbers read as plain text). */
.lot-page .lot-history .what a{color:var(--green);text-decoration:underline;text-decoration-color:#a9c9ad;text-underline-offset:3px}
.lot-page .lot-history .what a:hover{color:var(--green-dark);text-decoration-color:currentColor}
.lot-page .lot-history .what .text-btn{margin-left:10px;vertical-align:1px}
/* What moved nothing: a hold (a clock, no sign), a recall's stop (red), what was recorded after receiving. */
.lot-page .lot-history li.hold .q{font-weight:400;color:var(--ink-soft)}
.lot-page .lot-history li.stop .mark{background:var(--red-tint);color:var(--red-ink)}
.lot-page .lot-history li.stop .what{color:var(--red-ink)}
.lot-page .lot-history li.stop .what a{color:inherit;text-decoration-color:var(--red-line)}
.lot-page .lot-none{margin:0;font-size:15px;color:var(--ink-soft)}
.lot-page .entry-list .entry{font-size:15px}
.lot-page .entry-list .entry-name{flex-wrap:wrap;align-items:center;gap:4px 8px}
.lot-page .entry-list .entry-text small{line-height:1.45}
.lot-page .entry-list .entry-text small a{color:var(--green);text-decoration:underline;text-decoration-color:#a9c9ad}
.lot-page .entry-list .entry-text small a:hover{color:var(--green-dark);text-decoration-color:currentColor}
.lot-page .entry-actions{margin-left:12px}
.lot-page .lc-lead span{font-size:14.5px;color:var(--ink)}
.lot-page .lc-of{font-size:14px;color:var(--ink-soft)}
.lot-page .lc-of>b:first-child{font-size:15px;font-weight:600}
.lot-page .lc-why{font-size:14px;color:var(--ink)}
.lot-page .lc-split{margin-top:16px;font-size:14.5px}
.lot-page .lc-split .n{color:var(--ink)}
.lot-page .lc-split .k small{font-size:13.5px;color:var(--ink-soft)}
.lot-page .lc-split+.lc-split{margin-top:22px}
.lot-page .lc-link{display:inline-block;margin-top:14px}
.lot-page .lc-dl.read{margin-top:-4px}
.lot-page .lc-dl.read dd{overflow-wrap:anywhere}
.lot-page .lc-dl.read dd small{display:block;margin-top:2px;font-size:14px;color:var(--ink-soft)}
.lot-page .lc-dl.read dd .text-btn{margin-left:10px;vertical-align:1px}
/* The strip: second lines at the reading size; a link in one is the line's own colour. Past its product's days is AMBER (.aged); red
   is a recall's stop (.late). */
.lc-facts.lot-strip .lc-fact small{font-size:14px;line-height:1.45;color:var(--ink-soft)}
.lc-facts.lot-strip .lc-fact.late small{color:var(--red)}
.lc-facts.lot-strip .lc-fact.aged small{color:var(--amber-ink)}
.lc-fact.aged{border-top-color:var(--amber-edge);background:var(--amber-soft)}
.lc-fact.aged>strong,.lc-fact.aged small{color:var(--amber-ink)}
.lc-fact small a{color:inherit}
/* A recall's stop, first thing on the page: what stopped the lot, since when, and the way to the recall. The chip in the head opens it too. */
.lot-stop{display:flex;align-items:center;flex-wrap:wrap;gap:12px 14px;padding:16px 18px;border:1px solid var(--red-line);border-radius:14px;background:var(--red-tint)}
.lot-stop .entry-icon{display:grid;place-items:center;flex:none;width:36px;height:36px;border-radius:10px;background:#f6d9d1;color:var(--red-ink)}
.lot-stop .entry-text{flex:1 1 240px;min-width:0}
.lot-stop .entry-name{display:block;font-size:16px;font-weight:650;line-height:1.4;color:var(--red-ink)}
.lot-stop .entry-text small{display:block;margin-top:2px;font-size:14px;line-height:1.45;color:var(--ink)}
a.status{cursor:pointer;text-decoration:none}
a.status:hover{text-decoration:underline}
.check-label.lot-none-on-cases{margin:-6px 0 16px}
/* Where it went: a customer's documents a line each; the recall list at its foot. */
.lot-page .entry-list.went .entry-text small .tag{margin:0 0 0 6px;padding:0 8px}
/* The sign-in column (centred layout from the approved demo of 2026-10-09): the sign-in page and the loading page stand in it, so the logo
   stays where it was from signing in to the workspace opening. */
.auth{display:flex;min-height:100dvh;justify-content:center}
.auth-side{display:flex;align-items:center;justify-content:center;min-width:0;width:100%;padding:64px 24px}
.auth-form{display:flex;flex-direction:column;justify-content:flex-start;gap:0;width:100%;max-width:380px;min-height:0;margin-top:-64px}
.auth-mlogo{display:block;width:260px;max-width:100%;height:auto;align-self:center;margin:0 0 40px}
@media (max-width:760px){.auth-side{align-items:center;padding:40px 24px}.auth-form{margin-top:-40px}.auth-mlogo{width:220px;margin-bottom:34px}}
@media (max-height:560px){.auth-side{align-items:flex-start;padding-top:32px}.auth-form{margin-top:0}.auth-mlogo{margin-bottom:24px}}
/* The loading page (owner, 2026-10-13: "apply it"; reviews/loading-page-demo-2026-10-13): the logo, a moving line and "Opening your workspace";
   a failure is one line and one large button under the logo (boot.js). The step keeps the height of the sign-in step under the logo, so the
   logo does not move. It covers the whole window: the frame keeps room for the sidebar, which is not drawn yet. */
.connection-panel{position:fixed;inset:0;z-index:20;overflow:auto;background:var(--paper)}
.connection-step{display:grid;align-content:start;justify-items:center;gap:16px;min-height:222px;padding-top:6px;text-align:center}
.connection-step p{font-size:16px;color:var(--muted)}
@media (max-width:760px){.connection-step{min-height:218px}}
.connection-step.failed{justify-items:stretch;gap:12px;padding-top:2px}
.connection-step.failed p{margin-bottom:10px;font-size:17px;line-height:1.45;color:var(--ink)}
.connection-step .button.large{box-shadow:none}
.connection-bar{position:relative;width:180px;height:4px;border-radius:4px;background:var(--line);overflow:hidden}
.connection-bar::after{content:"";position:absolute;inset:0 auto 0 0;width:38%;border-radius:4px;background:var(--green);animation:connection-slide 1.25s cubic-bezier(.45,0,.25,1) infinite}
@keyframes connection-slide{from{transform:translateX(-100%)}to{transform:translateX(265%)}}
@media (prefers-reduced-motion:reduce){.connection-bar::after{animation:none;width:100%;opacity:.55}}
.connecting>:not(.connection-panel):not(script){display:none!important}

/* The shell's phone and tablet layout starts at 900px (the sidebar becomes the Menu sheet; see layout.css and boot.js). */
@media(max-width:900px){
.summary{padding:16px}
.summary>strong{font-size:24px}
.summary:has(.currency-total)>strong{font-size:20px}
.tabs,.lc-tabs{display:flex;width:100%}
.tabs button,.lc-tabs button{flex:1;min-height:36px;padding:6px 10px;font-size:13.5px}
.search{width:100%;max-width:none}
.table-toolbar,.toolbar,.filter-summary{padding:18px 16px 16px}
/* A toolbar on a phone or a tablet: the tabs take the full width, then the filters in two even columns with the search across both.
   Nothing is pushed to one side or left alone at an edge. */
.table-toolbar,.toolbar{display:grid;grid-template-columns:minmax(0,1fr);gap:14px}
.toolbar-filters{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;flex:none}
.toolbar-filters .search{grid-column:1/-1;min-width:0;max-width:none}
.toolbar-filters>.select-shell,.toolbar-filters>select,.toolbar-filters>.button{width:100%;min-width:0}
.toolbar-filters>:only-child,.toolbar-filters>.select-shell:nth-last-child(2):first-child{grid-column:1/-1}
.toolbar-filters.pills{display:flex;flex-wrap:wrap;gap:10px 8px}
.toolbar-filters.pills>.select-shell{width:auto}
.toolbar-filters.pills .search{flex-basis:100%;max-width:none;margin-left:0}
.table-footer,.billing-table-footer{padding:12px 16px}
.shipment-panel th:first-child,.shipment-panel td:first-child,.panel th:first-child,.panel td:first-child{padding-left:16px}
.shipment-panel th:last-child,.shipment-panel td:last-child,.panel th:last-child,.panel td:last-child{padding-right:16px}
.panel-top,.panel-body{padding-left:16px;padding-right:16px}
.poe-card{padding:18px 16px}
.poe-card>.poe-card-head:first-child{margin:-18px -16px 16px;padding:14px 16px}
.form-grid.three,.poe-grid-3{grid-template-columns:repeat(2,minmax(0,1fr))}
.toast,#billing-toast{left:50%}
}
/* Stacked list tables. When the workspace container is narrow (phones, tablets, a small window beside the sidebar) every
   .list-table is a list of cards instead of a sideways scroller: the header is hidden, each row is a block led by its
   anchor cell, and every other cell shows its column name from data-label. Numbers read left, .col-actions and .empty
   span the row, the row arrow is dropped. `table.list-table` outranks the per-table min-widths and cell paddings. */
@container workspace (max-width:820px){
table.list-table{display:block;min-width:0}
table.list-table thead{display:none}
table.list-table tbody{display:block}
table.list-table tbody tr{display:grid;grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:12px 16px;padding:14px 16px;border-bottom:1px solid var(--line-soft)}
table.list-table tbody tr:last-child{border-bottom:0}
table.list-table td,table.list-table td:first-child,table.list-table td:last-child{display:block;min-width:0;max-width:none;padding:0;border:0;text-align:left;white-space:normal}
table.list-table td.col-num{white-space:normal}/* a figure's note wraps in the card, never cut (review of 2026-09-29, A7) */
table.list-table.compact td,table.list-table.compact td:first-child,table.list-table.compact td:last-child{padding:0}
table.list-table td:first-child,table.list-table td.col-actions,table.list-table td.empty{grid-column:1/-1}
table.list-table td[data-label]::before{content:attr(data-label);display:block;margin-bottom:4px;font-size:12px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;line-height:1.4;color:var(--muted);white-space:nowrap}
table.list-table tbody tr.needs{background:var(--amber-soft)}
table.list-table td.col-actions .actions{justify-content:flex-start}
table.list-table td.col-actions:empty{display:none}
table.list-table td.col-wide{display:block}
table.list-table td.empty{padding:22px 8px;text-align:center}
table.list-table td small,.list-table td:first-child .row-anchor{max-width:none}
table.list-table .progress{margin-left:0}
}
/* Purchase-order and invoice item cards (see purchase.css, billing.css): a stacked cell reads left whatever its column holds. */
@container workspace (max-width:1000px){.poe-items-table td.col-num,.poe-items-table td.col-actions{text-align:left}}
/* Phones: every field grid is one column. */
@media(max-width:560px){.field-pair,.form-grid,.form-grid.three,.poe-grid-2,.poe-grid-3{grid-template-columns:1fr}}
/* Phones: the dialog fills the width and its buttons stack, primary on top. */
@media(max-width:560px){dialog.dialog,dialog.dialog.wide,dialog.dialog.confirm{width:calc(100% - 16px);max-height:calc(100dvh - 16px)}.dialog-head,.dialog-body,.dialog-foot,.confirm .dialog-body,.confirm .dialog-foot{padding-left:18px;padding-right:18px}.dialog-foot{flex-direction:column-reverse;align-items:stretch;gap:8px}.dialog-foot .button,.dialog-foot .text-btn{width:100%;justify-content:center}.dialog-foot .aside{margin-right:0}}
@media(prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important;scroll-behavior:auto!important}}
@media print{body{background:#fff!important}.toast,#billing-toast{display:none!important}}

/* Recalls (public/recall.js; owner, 2026-09-22, the search reworked 2026-09-23): the recalls list (.recall-table); Trace stock's ONE
   search box (.trace-box: the search mark, what was picked as a chip (.trace-chip) with its clear button, then the input, which is
   the shared typed picker FWCombo 'trace'); the lots it found (.trace-table: a tick per lot, a row left out muted (tr.off), the
   packing dates that narrow it (.trace-narrow), the answer in one line (.trace-answer)); the recall's page (.recall-page: the call
   list with what was logged (small.logged), the stopped lots, where the stock came from, the history). A lot a recall stops says so
   in red (.status.stopped); a customer not on record, or with no phone or email, says so in amber (.warn). */
.recall-table th:nth-child(1){width:34%}
.recall-table th:nth-child(2){width:26%}
.recall-table th:nth-child(3){width:22%}
.trace-table th:nth-child(1){width:34%}
.came-table th:nth-child(1){width:22%}
.came-table th:nth-child(2){width:26%}
.came-table th:nth-child(4){width:24%}
.trace-table th:nth-child(2){width:30%}
.recall-page>.poe-card{margin-bottom:16px}
.trace-box{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;min-height:54px;padding:6px 14px;border:1.5px solid var(--green-line);border-radius:12px;background:var(--surface);cursor:text}
.trace-box:focus-within{border-color:var(--green)}
.trace-box-icon{display:grid;place-items:center;color:var(--muted)}
.trace-box-icon svg{width:20px;height:20px}
.trace-box input{flex:1 1 200px;min-width:0;min-height:40px;border:0;outline:0;padding:6px 0;background:none;font-size:17px;box-shadow:none}
.trace-chip{display:inline-flex;align-items:center;gap:4px;max-width:100%;padding:3px 4px 3px 12px;border-radius:8px;background:var(--green-tint);color:var(--green-dark);font-size:15px;font-weight:600;overflow-wrap:anywhere}
.trace-chip .icon-button{width:28px;height:28px;min-height:28px;border:0;background:none;color:var(--green-dark)}
.trace-narrow{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;padding:0 0 12px;font-size:14.5px;color:var(--ink-soft)}
.trace-narrow .select-shell{width:auto;flex:0 1 190px}.trace-narrow .select-trigger{width:100%}
.trace-table tr.off td{color:var(--muted)}
.trace-table tr.off td strong,.trace-table tr.off .lot-no{color:var(--muted)}
.trace-answer{margin:14px 0 0;padding-top:14px;border-top:1px solid var(--line-soft);font-size:16px;line-height:1.55;color:var(--ink)}
.trace-answer b{font-weight:650}
.recall-page .entry-text small.logged{color:var(--muted)}
.field .opt{font-weight:400;color:var(--muted)}
.trace-pick{display:inline-flex;align-items:center;gap:10px}
.trace-pick input{flex:none;width:16px;height:16px;margin:0}
.trace-choices{display:grid;gap:10px;margin:0;padding:0;border:0}
.recall-page .entry-text small{font-size:14px;line-height:1.45;color:var(--ink-soft)}
.recall-page .entry-text small+small{margin-top:2px}
.recall-page .entry-text small .lot-no,.recall-page .lc-dl .lot-no{font-size:inherit}
.warn{color:var(--amber-ink)}

/* The count windows (.count-table; Count stock and a count on record): a lot per row, the ledger's figure, what was counted and, when
   short, why (.short tints it). */
.count-table{width:100%;border-collapse:collapse;font-size:15px}
.count-table th{padding:8px 10px;font-size:12px;font-weight:700;letter-spacing:.7px;text-transform:uppercase;color:var(--ink-soft);border-bottom:1px solid var(--line)}
.count-table td{padding:10px;border-bottom:1px solid var(--line-soft);vertical-align:top}
.count-table td small{display:block;margin-top:2px;font-size:14px;color:var(--ink-soft)}
.count-table input{width:100%;min-width:90px}
.count-table tr.short td{background:var(--amber-soft)}
/* The month picker of the Storage bills page (app.js monthPicker; owner, 2026-09-23; trimmed 2026-10-01): ‹ the month › in the page
   head and This month beside it; the twelve-month pop-up is gone. The bill of the month on screen is marked in the Bills card
   (.entry.shown, a green edge). */
.month-pick{display:inline-flex;align-items:center;gap:2px}
.month-pick .month-open{display:inline-flex;align-items:center;min-height:var(--control);padding:0 10px;font-size:15.5px;font-weight:600;color:var(--ink);white-space:nowrap}
.month-pick .icon-button:disabled{opacity:.35;cursor:default;background:transparent}
.entry-list .entry.shown{box-shadow:inset 3px 0 0 var(--green)}
@container workspace (max-width:560px){.month-pick{flex:1 1 100%;justify-content:space-between}}

/* Physical counts keep every input and its reason visible on narrow screens. */
@media(max-width:600px){.physical-count thead{display:none}.physical-count,.physical-count tbody,.physical-count tr,.physical-count td{display:block;width:100%}.physical-count tr{padding:10px 0;border-bottom:1px solid var(--line)}.physical-count td{border:0;padding:6px 0}.physical-count td[data-label]::before{content:attr(data-label);display:block;font-size:13px;color:var(--ink-soft);margin-bottom:4px}.physical-count input{min-width:0}.physical-count td.col-num{text-align:left}}

/* Tabs on a phone: every tab stays on screen; when they do not fit one row they wrap, and each row is filled edge to edge. */
@media(max-width:600px){.tabs,.lc-tabs{flex-wrap:wrap;overflow:visible;white-space:normal}.tabs>*,.lc-tabs>*{flex:1 1 auto;min-height:40px}}

.skip-link{position:fixed;top:8px;left:8px;z-index:10000;padding:12px;background:var(--surface);color:var(--ink);transform:translateY(-200%)}.skip-link:focus{transform:none}
@media(pointer:coarse),(max-width:600px){.button,.icon-button{min-height:44px}.entry-actions{gap:12px}}

@media(pointer:coarse),(max-width:600px){.button.small{min-height:44px}}
/* A text button and a back link sit in a line of text, so a finger's target is an area around them (44px tall), never a taller line. */
@media(pointer:coarse),(max-width:600px){.text-btn,.page-back>a,.page-back>button{position:relative}.text-btn::after,.page-back>a::after,.page-back>button::after{content:'';position:absolute;inset:-12px -8px}}
/* Storage bills is a window of Shipment inventory (owner, 2026-10-05): the month and the warehouse on one row at its top, the strip and
   the page's cards under them. .lc-ask is the bill window's block that asks for a product's units per skid once before the bill is saved. */
.storage-window{display:grid;gap:16px}
.storage-head-row{display:flex;flex-wrap:wrap;gap:10px 14px;align-items:center}
.storage-wh{font-size:15.5px;font-weight:600;color:var(--ink)}
.lc-ask{display:grid;gap:10px;padding:12px 14px;border:1px solid var(--amber-edge);background:var(--amber-soft);border-radius:12px}
.lc-ask>strong{font-size:15px;color:var(--amber-ink)}
.lc-ask>small{font-size:14px;color:var(--muted)}

.select-group{padding:8px 12px;font-size:12px;font-weight:700;color:var(--muted);background:var(--surface-soft)}

/* Credit card and decision footer follow the approved credit flow. */
.credit-card .entry-foot{display:flex;flex-direction:row;flex-wrap:wrap;gap:8px 22px}
.credit-card .entry.missing{flex-wrap:wrap}
.credit-card .entry.missing .entry-actions{margin-left:auto}
#credit-decision .entry-foot{display:flex;justify-content:space-between}

dialog.dialog.credit-window{width:min(780px,calc(100% - 32px))}

.profile-comparison{table-layout:fixed;width:100%}
.profile-comparison th{white-space:normal}
.profile-comparison td{overflow-wrap:anywhere}

@media(max-width:600px){.profile-comparison,.profile-comparison tbody,.profile-comparison tr,.profile-comparison td{display:block;width:100%}.profile-comparison thead{display:none}.profile-comparison tr{padding:12px 0;border-bottom:1px solid var(--line-soft)}.profile-comparison td{padding:4px 12px;border:0}.profile-comparison td:first-child{font-weight:600}}
