/* ==========================================================================
   Inventory: the "utilitarian" direction picked on 2026-10-10. Built from
   docs/mockups/utilitarian.css and adapted to the app's markup.
   Light grey header bar, dense full-grid tables like a spreadsheet, the
   system UI font, strong 1px borders, compact spacing. Colour only for
   meaning (red = bad, amber = warn, green = ok), always next to words.
   System fonts only. No radius, shadows, gradients, images or motion.
   ========================================================================== */

/* --- 1. Tokens ----------------------------------------------------------- */
:root {
  color-scheme: light;
  --bg: #ffffff;
  --text: #161616;
  --muted: #5a5a5a;
  --bar: #e2e2e2;             /* header bar */
  --panel: #f2f2f2;           /* table heads, toolbars, totals, facts labels */
  --line: #8a8a8a;            /* strong outer borders */
  --grid: #c6c6c6;            /* cell grid */
  --control: #6e6e6e;         /* form control and button borders */
  --hover: #e9e9e9;
  --bad: #b3261e;  --bad-bg: #fdeceb;
  --warn: #835200; --warn-bg: #fff2d1;
  --ok: #1e6b34;   --ok-bg: #e4f2e7;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "Liberation Sans", Arial, sans-serif;
  --mono: ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;
}

/* --- 2. Base ------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; border-radius: 0; }   /* square corners everywhere */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--text); font: 14px/1.4 var(--font); }
[hidden] { display: none !important; }   /* app.js shows and hides buttons with it */
h1, h2 { margin: 0; line-height: 1.25; }
h1 { font-size: 19px; }
p { margin: 0 0 8px; }
a { color: var(--text); text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 2px solid #000; outline-offset: 1px; }
code, .mono { font-family: var(--mono); font-size: 13px; }
.muted { color: var(--muted); }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
span.bad, td.bad { color: var(--bad); font-weight: 600; }
span.warn, td.warn { color: var(--warn); font-weight: 600; }

/* --- 3. Page frame: grey header bar of cells, section tabs, phone bar ------ */
header.top { display: flex; flex-wrap: wrap; align-items: stretch; background: var(--bar);
  border-bottom: 1px solid var(--line); }
.brand { display: flex; align-items: center; padding: 0 14px; color: inherit; font-weight: 700;
  text-decoration: none; border-right: 1px solid var(--line); white-space: nowrap; }
nav.main { flex: 1; display: flex; flex-wrap: wrap; align-items: stretch; }
nav.main > a, details.menu > summary { display: block; padding: 7px 12px; color: var(--text);
  text-decoration: none; border-right: 1px solid #c4c4c4; }
nav.main > a:hover, details.menu > summary:hover { background: #d2d2d2; }
/* The open page: a white, bold cell in the bar; inside a menu, a bold entry. */
nav.main [aria-current], details.menu > summary.current { background: var(--bg); font-weight: 700; }
.menu:has([aria-current]) > summary { background: var(--bg); font-weight: 700; }
header.top a:focus-visible, header.top summary:focus-visible { outline-offset: -3px; }  /* inside the cell */
/* New sale: the one black cell, always there. */
header.top .newsale { display: flex; align-items: center; padding: 0 16px; background: #1f1f1f; color: #fff;
  font-weight: 600; text-decoration: none; border-left: 1px solid var(--line); }
header.top .newsale:hover, header.top .newsale[aria-current] { background: #3a3a3a; }
details.menu.account > summary { height: 100%; border-right: 0; border-left: 1px solid #c4c4c4; }
details.menu.account ul { left: auto; right: 0; }
details.menu.account li form { margin: 0; }
details.menu.account li button.link { display: block; width: 100%; padding: 5px 12px; text-align: left;
  text-decoration: none; }
details.menu.account li button.link:hover { background: var(--hover); }
details.menu { position: relative; }
details.menu > summary { cursor: pointer; list-style: none; }
details.menu > summary::-webkit-details-marker { display: none; }
details.menu > summary::after { content: " \25BE"; }
details.menu[open] > summary { background: var(--bg); }
details.menu ul { position: absolute; z-index: 10; top: 100%; left: 0; min-width: 170px; margin: 0;
  padding: 2px 0; list-style: none; background: var(--bg); border: 1px solid var(--line); }
details.menu li a { display: block; padding: 5px 12px; text-decoration: none; }
details.menu li a:hover { background: var(--hover); }
/* The open section's pages, as a row of square tabs under the header bar. */
nav.tabs { display: flex; flex-wrap: wrap; background: var(--panel); border-bottom: 1px solid var(--line); }
nav.tabs a { display: block; padding: 5px 12px; color: var(--text); font-size: 13px; text-decoration: none;
  border-right: 1px solid var(--grid); white-space: nowrap; }
nav.tabs a:hover { background: var(--hover); }
nav.tabs a[aria-current] { background: var(--bg); font-weight: 700; }
nav.quick { display: none; }   /* the phone bar: see 14 */
table.grid.hub td a { display: block; padding: 4px 0; }   /* More: every row is one big link */

/* --- 4. Main area, page heading, sections -------------------------------- */
main { max-width: 1400px; padding: 12px 16px 32px; }
/* Where the page sits, above its title: "Items › BPC-157 10mg ›" (replaces Back buttons). */
nav.crumbs { margin: 0 0 4px; font-size: 13px; color: var(--muted); }
nav.crumbs a { color: var(--muted); }
nav.crumbs a:hover { color: var(--text); }
.pagehead { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 16px; margin: 0 0 12px; padding: 0 0 8px; border-bottom: 1px solid var(--line); }
.pagehead .actions { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }
section { margin: 22px 0 0; }
/* Section headings, and the heading of a group of fields: small grey capitals. */
h2, form > fieldset > legend { margin: 0 0 6px; padding: 0; font-size: 12px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }

/* --- 5. Messages and the form error summary ------------------------------
   The label before each message is added here, so message text should not
   start with "Done", "Warning" or "Error" itself. */
.messages { margin: 0 0 12px; }
.msg, .errors { margin: 0 0 6px; padding: 6px 10px; border: 1px solid; }
main > .msg { margin-bottom: 12px; }     /* a notice on its own, outside .messages */
.msg::before { font-weight: 700; }
.msg.info { border-color: var(--line); background: var(--panel); }
.msg.ok { border-color: var(--ok); background: var(--ok-bg); }
.msg.ok::before { content: "Done: "; color: var(--ok); }
.msg.warn { border-color: var(--warn); background: var(--warn-bg); }
.msg.warn::before { content: "Warning: "; color: var(--warn); }
.msg.bad, .errors { border-color: var(--bad); background: var(--bad-bg); }
.msg.bad::before { content: "Error: "; color: var(--bad); }
.errors { margin-bottom: 12px; font-weight: 700; color: var(--bad); }
.errors p { margin: 0; }

/* --- 6. Status tags ---------------------------------------------------------
   A tag with no level (ARCHIVED, VOID, QUOTE, EXPIRED...) is neutral grey. */
.tag { display: inline-block; padding: 0 4px; border: 1px solid var(--line); background: var(--panel);
  color: var(--text); font-size: 11px; font-weight: 700; line-height: 15px; letter-spacing: .03em;
  white-space: nowrap; }
.tag.bad { color: var(--bad); border-color: var(--bad); background: var(--bad-bg); }
.tag.warn { color: var(--warn); border-color: var(--warn); background: var(--warn-bg); }
.tag.ok { color: var(--ok); border-color: var(--ok); background: var(--ok-bg); }
.grid .phone-only { display: none; }   /* a short tag standing in for a column a phone leaves out */

/* --- 7. Tables: a full spreadsheet grid ------------------------------------ */
.table-wrap { overflow-x: auto; margin: 0 0 12px; }
table.grid { width: 100%; border-collapse: collapse; font-size: 13px; font-variant-numeric: tabular-nums; }
.grid th, .grid td { padding: 3px 7px; text-align: left; vertical-align: baseline; border: 1px solid var(--grid); }
.grid .num { text-align: right; }
.grid thead th { background: var(--panel); border-bottom-color: var(--line); font-weight: 600;
  vertical-align: bottom; white-space: nowrap; }
.grid tr.group th { background: #e8e8e8; font-weight: 700; }
.grid:not(.doc-lines) tbody tr:not(.group):hover > * { background: #f6f6f6; }
.grid tr.total > * { background: var(--panel); font-weight: 700; border-top: 2px solid var(--line); }
.grid tr.inactive > * { color: var(--muted); }
.grid td.actions { white-space: nowrap; }
.grid td.actions > * + * { margin-left: 10px; }
/* The row a link points at (base prices, #item-<id>): heavy rules above and below it. */
.grid tr:target { scroll-margin-top: 48px; }
.grid tr:target > * { border-top: 2px solid var(--text); border-bottom: 2px solid var(--text); }

/* --- 8. Forms: native controls, square, a visible label on every field --- */
form.narrow { max-width: 440px; }
form.inline { display: inline; }
.field { margin: 0 0 10px; }
.form .field { max-width: 560px; }
.field > label, .field legend { display: block; margin: 0 0 2px; padding: 0; font-size: 12px; font-weight: 600; }
/* A checkbox comes before its label; its hint and errors go on lines of their own. */
.field.check { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 6px; }
.field.check > label { display: inline; margin: 0; font-size: inherit; font-weight: normal; }
.field.check .hint, .field.check .error, .field.check > div { flex-basis: 100%; }
.field .hint ul { margin: 2px 0 0; padding-left: 18px; }   /* the password rules */
fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
form > fieldset { margin: 16px 0 0; }   /* a group of fields, e.g. Refund when cancelling */
.row { display: flex; flex-wrap: wrap; gap: 0 12px; }
.row > .field { flex: 1 1 180px; }
.choices { display: flex; flex-wrap: wrap; gap: 3px 18px; }
.choices label { display: inline-flex; align-items: baseline; gap: 5px; font-weight: normal; }
input, select, textarea, button { margin: 0; font: inherit; color: inherit; }
input[type=checkbox], input[type=radio] { accent-color: var(--text); }   /* ticked boxes black, not blue */
input:not([type=checkbox], [type=radio]), select, textarea { max-width: 100%; padding: 3px 5px;
  border: 1px solid var(--control); background: #fff; }
input:not([type=checkbox], [type=radio], [type=file]), select { height: 2em; }
input[type=search] { -webkit-appearance: textfield; appearance: textfield; }
/* The COA upload's Browse button: square like every other button. */
input[type=file]::file-selector-button { margin: 0 8px 0 0; padding: 2px 12px; border: 1px solid var(--control);
  border-radius: 0; background: #f0f0f0; color: var(--text); font: inherit; cursor: pointer; }
input[type=file]::file-selector-button:hover { background: #e0e0e0; }
.form .field > :is(input:not([type=checkbox], [type=radio], [type=number], .money, .pct, .qty), select, textarea) { width: 100%; }
textarea { width: 100%; }
textarea.quote-text { min-height: 220px; font: 13px/1.5 var(--mono); }
input.money, input.pct, input.qty, input[type=number] { width: 110px; text-align: right;
  font-variant-numeric: tabular-nums; }
input.qty, .lines input[type=number] { width: 72px; }
input.size { width: 112px; }   /* Other size, on the Add items pick list */
.hint { margin: 2px 0 0; font-size: 12px; color: var(--muted); }
.error { margin: 2px 0 0; font-size: 12px; font-weight: 700; color: var(--bad); }
.has-error > label { color: var(--bad); }
.has-error :is(input, select, textarea), :is(input, select, textarea)[aria-invalid=true] {
  border-color: var(--bad); background: var(--bad-bg); }

/* Line tables: a control in each cell (sale and purchase lines, prices). */
.lines .field { margin: 0; }
.lines td { padding: 3px 4px; }
.lines select { width: 100%; min-width: 230px; }
/* Price each on sale lines: a narrower money box; greyed, it shows the tier's price. */
.lines input.money { width: 92px; }
.lines input::placeholder { color: var(--muted); opacity: 1; }
.lines td .hint { white-space: nowrap; }
table.grid td .error { white-space: normal; text-align: left; }
/* The live cost per vial on purchase lines needs app.js, so its column shows only with it. */
table.grid.lines .estimate { display: none; }
table.grid.lines.live .estimate { display: table-cell; }
p.sum { font-weight: 600; font-variant-numeric: tabular-nums; }
/* The Add items pick list: ticks for each size of a product. */
table.picklist .choices { gap: 2px 16px; }
table.picklist th .muted { font-weight: normal; }

/* A page's More menu: rarely used or destructive actions, listed under a button. */
.actions details.menu.more { position: relative; }
.actions details.menu.more > summary { padding: 4px 14px; border: 1px solid var(--control); background: #f0f0f0;
  line-height: 18px; }
.actions details.menu.more > summary:hover, .actions details.menu.more[open] > summary { background: #e0e0e0; }
.actions details.menu.more ul { top: calc(100% + 2px); left: auto; right: 0; min-width: 200px; }
details.menu li form { margin: 0; }
details.menu li button.link { display: block; width: 100%; padding: 5px 12px; text-align: left;
  text-decoration: none; }
details.menu li button.link:hover { background: var(--hover); }
details.menu li .bad { color: var(--bad); }
/* "What do these mean?": the longer explanation of a page, folded away. */
details.help { max-width: 760px; margin: 6px 0 12px; font-size: 13px; color: var(--muted); }
details.help > summary { width: max-content; max-width: 100%; color: var(--text); cursor: pointer; }
details.help[open] > summary { margin-bottom: 4px; }
details.help p { margin: 0 0 6px; }

/* --- 9. Buttons: plain rectangles ------------------------------------------ */
button, .button { display: inline-block; padding: 4px 14px; border: 1px solid var(--control);
  background: #f0f0f0; color: var(--text); line-height: 18px; text-align: center;
  text-decoration: none; cursor: pointer; }
button:hover, .button:hover { background: #e0e0e0; }
button:active, .button:active { background: #d0d0d0; }
.primary { border-color: #000; background: #1f1f1f; color: #fff; font-weight: 600; }
.primary:hover, .primary:active { background: #3a3a3a; }
.danger { border-color: var(--bad); background: #fff; color: var(--bad); }
.danger:hover, .danger:active { background: var(--bad-bg); }
button.link { padding: 0; border: 0; background: none; color: inherit; line-height: inherit;
  text-decoration: underline; text-underline-offset: 2px; }
button.link:hover, button.link:active { background: none; text-decoration-thickness: 2px; }
.buttons { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 12px 0; }
/* Add selected items stays in view at the foot of the long pick list. */
.sticky-actions { position: sticky; bottom: 0; margin-top: 0; padding: 8px 0; background: var(--bg);
  border-top: 1px solid var(--line); }

/* --- 10. Filters toolbar and pager ----------------------------------------- */
/* Every item in the toolbar is one control high and they line up along the top, so a hint
   or an error under a field does not push the buttons and links out of line. */
.filters { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px 16px; margin: 0 0 10px;
  padding: 6px 8px; background: var(--panel); border: 1px solid var(--line); }
.filters .field { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 5px; min-height: 2em; margin: 0; }
.filters .field > label { margin: 0; font-size: inherit; font-weight: normal; }
/* A hint or errors go under the control and never make the field wider than it. */
.filters .field > div { flex-basis: 100%; contain: inline-size; }
.filters > a:not(.button) { line-height: 2em; }
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px;
  margin: 6px 0 12px; font-size: 13px; }
.pager a, .pager [aria-disabled] { padding: 2px 10px; border: 1px solid var(--control); background: #f0f0f0;
  text-decoration: none; }
.pager a:hover { background: #e0e0e0; }
.pager [aria-disabled] { border-color: var(--grid); background: #fafafa; color: var(--muted); }

/* --- 11. Facts list: a property sheet -------------------------------------- */
dl.facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); max-width: 680px;
  margin: 0 0 12px; border: 1px solid var(--line); font-size: 13px; }
dl.facts dt, dl.facts dd { margin: 0; padding: 3px 8px; border-top: 1px solid var(--grid); }
dl.facts dt:first-of-type, dl.facts dt:first-of-type + dd { border-top: 0; }
dl.facts dt { background: var(--panel); border-right: 1px solid var(--grid); font-weight: 600; }
dl.facts dd { overflow-wrap: anywhere; }   /* long file paths on the system check */

/* --- 12. Quote document (customer-facing) and other page shells ---------- */
.doc { max-width: 760px; margin: 0 0 12px; padding: 28px 32px 32px; background: #fff; border: 1px solid var(--line); }
.doc-head { display: grid; grid-template-columns: 1fr auto; column-gap: 24px; align-items: baseline;
  margin: 0 0 18px; padding: 0 0 8px; border-bottom: 2px solid var(--text); }
.doc-head h1 { grid-row: span 2; font-size: 22px; }
.doc-head p { margin: 0; text-align: right; }
.doc-lines { font-size: 14px; }
.doc-total { margin: 0; padding: 5px 7px; text-align: right; font-size: 15px; font-weight: 700;
  font-variant-numeric: tabular-nums; background: var(--panel); border: 1px solid var(--line); border-top: 0; }
.doc .cancelled { display: inline-block; margin: 12px 0 0; padding: 2px 8px; border: 2px solid var(--bad);
  color: var(--bad); font-weight: 700; letter-spacing: .08em; }
.doc h1 .cancelled { margin: 0; }
/* Print, back, plain text and copy, under the sheet and as wide as it. */
.noprint { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; max-width: 760px; margin: 0 0 12px; }
body.print { padding: 16px; }                      /* the quote page has no header */
body.bare main { max-width: 380px; margin: 12vh auto 0; }
body.bare h1 { margin-bottom: 14px; }              /* login and the error pages */
.login h1 { font-size: 20px; }

/* --- 13. Print -------------------------------------------------------------
   A zero page margin leaves the browser no room for its URL/date lines;
   the body padding becomes the real margin (cloned onto every page).
   The quote prints as it looks; list pages drop their controls and print
   their tables small. */
@media print {
  @page { margin: 0; }
  body, body.print { padding: 15mm 17mm; background: #fff;
    -webkit-box-decoration-break: clone; box-decoration-break: clone; }
  header.top, nav, .noprint, .messages, .buttons, .filters, .pagehead .actions, form.inline, td.actions {
    display: none !important; }
  main { max-width: none; margin: 0; padding: 0; }
  .doc { width: 100%; max-width: none; margin: 0; padding: 0; border: 0; }
  .table-wrap { overflow: visible; }
  a { text-decoration: none; }
  thead { display: table-header-group; }
  tr { break-inside: avoid; }
  table.grid:not(.doc-lines) { font-size: 8.5pt; }
  table.grid:not(.doc-lines) thead th { white-space: normal; }
  table.grid:not(.doc-lines) :is(th, td) { padding: 2px 4px; }
  .grid thead th, .grid tr.group th, .grid tr.total > *, .doc-total, .tag, .msg, .doc .cancelled {
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* --- 14. Narrow screens (700px and below) --------------------------------- */
@media (max-width: 700px) {
  /* The header is one row: the name and the account menu. The sections move to a bar fixed
     at the foot of the screen (nav.quick), with "+ Sale" in the middle and More for the rest. */
  header.top nav.main, header.top .newsale { display: none; }
  .brand { flex: 1 1 auto; padding: 10px 14px; border-right: 0; }
  details.menu.account > summary { padding: 10px 14px; }
  /* An open menu drops a full-width list under its row: a menu at the end of a row
     would otherwise run off the right edge of the screen. */
  header.top { position: relative; }
  details.menu { position: static; }
  details.menu ul { top: auto; left: 0; right: 0; min-width: 0; }
  details.menu li a, details.menu.account li button.link { padding: 10px 14px; }
  /* A page's More menu opens in place under its button, so it never runs off the screen. */
  .actions details.menu.more ul { position: static; min-width: 0; margin-top: 2px; }
  details.menu li button.link { padding: 10px 14px; }
  /* The tabs wrap onto a second row rather than scroll, so none is out of sight. */
  nav.tabs a { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; min-height: 44px;
    padding: 0 14px; font-size: 14px; border-bottom: 1px solid var(--grid); }
  /* Text and controls sized for a phone (owner, 19 Oct 2026): 16px text in every box, so iPhone
     Safari does not zoom in when one is tapped, and boxes and buttons at least 44px high. */
  body { font-size: 16px; }
  table.grid { font-size: 14px; }
  .grid :is(th, td) { padding: 3px 5px; }   /* narrower cells: more columns fit */
  .hint, .error, .field > label, .field legend, details.help, nav.crumbs, .pager, dl.facts { font-size: 14px; }
  input:not([type=checkbox], [type=radio], [type=file]), select, textarea { font-size: 16px; }
  input:not([type=checkbox], [type=radio], [type=file]), select { height: auto; min-height: 44px; padding: 6px 8px; }
  input[type=checkbox], input[type=radio] { width: 20px; height: 20px; }
  button:not(.link), .button { min-height: 44px; padding: 6px 14px; }
  .button, .actions details.menu.more > summary { display: inline-flex; align-items: center; justify-content: center; }
  .actions details.menu.more > summary { min-height: 44px; }
  button.link { min-height: 32px; }   /* Take off, Log out: a text link, but still a fair target */
  nav.quick { display: grid; grid-template-columns: repeat(5, 1fr); position: fixed; left: 0; right: 0; bottom: 0;
    z-index: 20; background: var(--bar); border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom); }
  nav.quick a { display: flex; align-items: center; justify-content: center; min-height: 48px; padding: 0 4px;
    color: var(--text); font-size: 13px; text-align: center; text-decoration: none; border-right: 1px solid #c4c4c4; }
  nav.quick a:last-child { border-right: 0; }
  nav.quick a[aria-current] { background: var(--bg); font-weight: 700; }
  nav.quick a.sale { background: #1f1f1f; color: #fff; font-weight: 700; }
  nav.quick a.sale[aria-current] { background: #3a3a3a; }
  main { padding: 10px 16px 72px; }   /* room above the phone bar */
  .sticky-actions { bottom: 48px; }
  .row > .field { flex-basis: 100%; }
  .table-wrap { overscroll-behavior-x: contain; }
  /* One line per row; the frame scrolls. Cells that span columns (group headings,
     "nothing yet" notes) still wrap, so they do not stretch the table, and so do the
     Add items pick list, Today's Getting started and the text column of a two-column table. */
  .table-wrap .grid:not(.picklist, .steps) :is(th, td):not([colspan]) { white-space: nowrap; }
  .table-wrap .grid:not(:has(:is(th, td):nth-child(3))) :is(th, td):last-child:not(.num) { white-space: normal; }
  .grid .wide-only { display: none; }   /* a column a phone can do without (Today's lists) */
  .grid .phone-only { display: inline-block; }
  .grid :is(th, td).phone-only { display: table-cell; }   /* a cell standing in for several (a Total label) */
  .grid.todo :is(th, td) { padding: 3px 5px; }
  .grid.todo td.actions .button { padding: 1px 6px; }
  /* Sale lines on a phone: product, quantity and price in view; tags and lot hints wrap. */
  .lines select { min-width: 120px; }
  .lines input.qty { width: 52px; }
  .lines input.money { width: 72px; }
  .table-wrap .grid:not(.picklist) :is(td, th).wrap, .lines td .hint { white-space: normal; }
  /* Line tables marked "cards" (sale and purchase lines): each line becomes a small block, its
     first cell across the top and the rest three to a row, each under its column's name
     (data-label), so nothing runs off the screen. */
  .table-wrap:has(> table.cards) { overflow: visible; }
  table.cards > thead { display: none; }
  table.cards, table.cards > tbody, table.cards > tfoot { display: block; }
  table.cards > tbody > tr { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px 8px;
    padding: 10px 0; border-bottom: 1px solid var(--grid); }
  table.cards > tbody > tr > * { display: block; min-width: 0; padding: 0; border: 0; background: none;
    text-align: left; white-space: normal; }
  table.cards > tbody > tr > :is(.card-full, [data-check]) { grid-column: 1 / -1; }
  table.cards > tbody > tr > .num { text-align: left; }
  table.cards > tbody > tr > [data-check]:empty, table.cards > tbody > tr > [data-n] { display: none; }
  table.cards > tbody > tr > [data-label]::before { content: attr(data-label); display: block; font-size: 12px;
    color: var(--muted); }
  table.cards :is(select, input:not([type=checkbox])) { width: 100%; min-width: 0; }
  table.cards.live > tbody > tr > .estimate { display: block; }
  table.cards > tfoot > tr { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 16px;
    padding: 6px 0; border-top: 2px solid var(--line); font-weight: 700; }
  table.grid.cards > tfoot > tr > * { padding: 0; border: 0; background: none; }
  table.cards > tfoot > tr > :empty { display: none; }
  table.cards > tfoot > tr > [data-label]::before { content: attr(data-label) " "; font-weight: 400; color: var(--muted); }
  dl.facts { grid-template-columns: minmax(0, 1fr); }
  dl.facts dt { border-right: 0; }
  dl.facts dd { border-top: 0; }
  .pager { justify-content: flex-start; }
  .doc { padding: 16px 14px 20px; }
  .doc-head { display: block; }
  .doc-head h1 { margin-bottom: 4px; }
  .doc-head p { text-align: left; }
}

/* --- 15. The quote lines form (new sale, edit quote): the mockup's 980px column ---- */
form.lines-form, form[data-sale-form] { max-width: 980px; }
/* A folded part of a form ("Sale date and supplies"): a grey bar that opens a framed panel. */
details.adjust { margin: 22px 0 0; border: 1px solid var(--line); }
details.adjust > summary { padding: 6px 10px; background: var(--panel); font-weight: 600; cursor: pointer; }
details.adjust[open] > summary { border-bottom: 1px solid var(--line); }
details.adjust > :not(summary) { margin-left: 10px; margin-right: 10px; }
details.adjust > summary + * { margin-top: 10px; }
details.adjust > :last-child { margin-bottom: 10px; }
details.adjust > h2 { margin-top: 16px; }
/* A button in a table row (Today's actions): compact, so the rows stay one line high. */
.grid td.actions .button { padding: 1px 10px; line-height: 17px; }
/* Getting started on Today: a numbered checklist, done steps greyed. */
table.grid.steps { width: auto; min-width: min(100%, 560px); }
.salebar { display: none; }   /* New sale's total bar: phones only (14) */
/* Inventory's Category, Stock and archived filters: folded on a phone, always open on a wider
   screen (app.js opens them; the Filters label then hides). */
details.more-filters > summary { line-height: 2em; cursor: pointer; }
details.more-filters > div { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 6px 16px; }
details.more-filters[open] > summary { margin-bottom: 6px; }
@media (min-width: 701px) { details.more-filters[open] > summary { display: none; } }

/* --- 16. Today (owner, 19 Oct 2026): the month in four boxes, then To do beside Restock and
   Latest sales. Each To do list has a coloured edge for how urgent it is (red: overdue or
   cancelled; amber: waiting on you; grey: for information), always next to its words. */
.kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0 0 18px; border: 1px solid var(--line); }
.kpi { display: grid; align-content: start; gap: 2px; padding: 10px 14px; color: var(--text); text-decoration: none;
  border-right: 1px solid var(--grid); }
.kpi:last-child { border-right: 0; }
.kpi:hover { background: var(--hover); }
.kpi .k-label { font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.kpi .k-num { font-size: 24px; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
.kpi .k-sub { font-size: 13px; color: var(--muted); }
.today-cols { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 18px; align-items: start; }
.today-side { display: grid; gap: 18px; }
.today-cols section { margin: 0; }
.panel { border: 1px solid var(--line); }
.panel > h2 { margin: 0; padding: 7px 12px; background: var(--panel); border-bottom: 1px solid var(--line); }
.pagehead h1 .muted { font-size: 15px; font-weight: 400; }
.panel > p { margin: 8px 12px; }
.panel > .table-wrap { margin: 8px 12px; }
.todo-group { border-left: 4px solid var(--grid); }
.todo-group + .todo-group, .restock + .todo-group, .panel > p + .todo-group { border-top: 1px solid var(--grid); }
.todo-group.bad { border-left-color: var(--bad); }
.todo-group.warn { border-left-color: var(--warn); }
.todo-group.ok { border-left-color: var(--ok); }
.todo-group > h3 { margin: 0; padding: 8px 12px 0; font-size: inherit; }
.todo-group > h3 .muted { font-weight: 400; }
.todo-group > p { margin: 4px 12px 8px; }
ul.rows { margin: 0; padding: 2px 0 4px; list-style: none; }
ul.rows > li { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px;
  padding: 6px 12px; }
ul.rows > li + li { border-top: 1px dotted var(--grid); }
ul.rows .main { flex: 1 1 14em; min-width: 0; }
ul.rows .sub { display: block; font-size: 13px; color: var(--muted); }
ul.rows .num { flex: none; }
ul.rows form.inline { flex: none; }
.restock { display: grid; gap: 8px; padding: 10px 12px; }
.restock .actions { display: flex; flex-wrap: wrap; gap: 6px; }

/* --- 17. Narrow screens, for sections 15 and 16 (after them, so these win) ---- */
@media (max-width: 700px) {
  /* New sale: the total and Complete sale stay in view above the phone bar. */
  .salebar { display: flex; align-items: center; justify-content: space-between; gap: 12px; position: fixed;
    left: 0; right: 0; bottom: calc(48px + env(safe-area-inset-bottom)); z-index: 19; padding: 6px 16px;
    background: var(--bg); border-top: 1px solid var(--line); font-variant-numeric: tabular-nums; }
  main:has(.salebar) { padding-bottom: 132px; }
  /* Today: the month's four numbers two by two, then everything in one column. */
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi:nth-child(2n) { border-right: 0; }
  .kpi:nth-child(-n+2) { border-bottom: 1px solid var(--grid); }
  .kpi .k-num { font-size: 22px; }
  .today-cols { grid-template-columns: minmax(0, 1fr); }
}
