/* ==========================================================================
   Purchase Orders — the module's shared stylesheet
   (purchase-orders.html, purchase-order-new.html, purchase-order.html,
    purchase-orders-reorder.html, purchase-orders-quotes.html,
    purchase-order-quote.html, suppliers.html, supplier.html, arrivals.html,
    arrival.html, arrival-packing-list.html, arrival-receive.html,
    purchase-orders-bills.html, purchase-order-bill.html,
    purchase-orders-claims.html, purchase-order-claim.html,
    purchase-orders-analytics.html, purchase-order-share.html,
    settings-purchase-orders.html)

   Spec: build/po/pages.md → "Shared stylesheet contract"

   One module, nineteen pages, one vocabulary: the buying side, from the
   reorder line to the slab in the yard, costed and paid. Everything here is a
   thing more than one Purchase Orders page says — a reading written as words,
   the mode a PO ships by, its Vava link, an ETA that slipped, the fill of a
   container, the path a status walks, the supplier thread, the three-way
   match. The `po-` prefix names that vocabulary rather than any one page.
   What belongs to one page (its register's column shares, how it folds on a
   phone) lives in that page's own `css/pages/<page>.css`.

   orders.css IS NOT LINKED on these pages. The shell every page copies from
   orders.html carries six helper classes that orders.css defines; they are
   restated first, under the same names, so the shell stays verbatim.

   TOKENS ONLY, LIGHT THEME ONLY. Every colour is a `var(--color-…)` read off
   app.css, so the dark themes inherit without a block of their own here and
   nothing below draws a hex. Radius never passes 7px (memory.md §2), nothing
   is set under 10px (§4), and a reading is a WORD, never a filled chip: colour
   on a badge means a state (§19), so a supplier type, a country, a mode, an
   incoterm or a count is grey text joined by `·`.

   NO `style` ATTRIBUTE ANYWHERE IN THE MODULE (§14). A bar or gauge width
   travels as an SVG `width` attribute inside `viewBox="0 0 100 6"` — a
   presentation attribute, not a style — exactly as `.ord-fill` does.
   ========================================================================== */

/* ---------- Shell helpers (restated from orders.css) -------------------------
   The shell is orders.html's, copied verbatim: the notifications menu's width,
   the icon in each of its rows, the centred "View Data-Quality Report" link,
   the Export PDF image link, the video button's blue icon and a dropdown's
   containing block are classes there, not inline styles. orders.css is not
   linked here, so the six rules are said again, once, for all nineteen pages.
   Lucide copies the <i>'s class onto the <svg> it draws, so `.ord-menu-ico`
   goes on the <i>: 15px puts a menu icon under the cap height of a 13px row. */
.ord-rel { position: relative; }
.ord-menu--wide { min-width: 328px; }
.ord-menu-ico { width: 15px; height: 15px; flex: none; }
.ord-menu-link--center { justify-content: center; color: var(--color-primary-700); font-weight: 500; }
.ord-export { display: inline-flex; align-items: center; cursor: pointer; }
.ord-export img { height: 34px; width: auto; }
.ord-ico-primary { color: var(--color-primary); }

/* ---------- The hub strip ----------------------------------------------------
   Eight registers, one strip, drawn attached to each page's own panel
   (memory.md §17). The tabs are LINKS — each one is another page — so `a.tab`
   has to sit exactly as `button.tab` does: no underline. The strip never
   carries `data-tabs`; app.js would read it as in-page tabs. The count TRAILS
   the label ("Reorder 12") where app.css's `.tab .count` expects it to lead,
   so it gives back the strip's fluid gap and keeps a fixed 4px to its word. */
.po-hub .tab,
.po-hub .tab:hover,
.po-hub .tab:focus-visible { text-decoration: none; }
.po-hub .tab .count {
  margin-right: 0;
  margin-left: calc(4px - clamp(4px, 0.3vw + 2.2px, 8px));
}

/* ---------- The panel the strip attaches to ----------------------------------
   The hub shell is `.tabs--attached.po-hub` + `.tab-shell` + ONE `.card`.
   app.css merges a card into its shell only through a `[data-tab-panel]`
   wrapper, and this strip has no panels, so without these rules the card
   would draw a second white box 16px inside the white shell (memory.md §13,
   §17). The card gives up its chrome and keeps its header, body and
   dividers; a table drops its side inset because the shell's own 16px already
   stands it off (§20) — whether it sits straight in the card or inside one of
   the card's `[data-view-panel]`s. */
.po-hub ~ .tab-shell > .card { background: none; border: 0; border-radius: 0; box-shadow: none; }
.po-hub ~ .tab-shell > .card > .card-header:first-child { padding-top: 0; }
.po-hub ~ .tab-shell > .card:first-child > .card-body:first-child { padding-top: 0; }
.po-hub ~ .tab-shell > .card > .table-wrap,
.po-hub ~ .tab-shell > .card > [data-view-panel] > .table-wrap { padding-inline: 0; }
/* THE HEAD BAND COMES OFF ONLY WHILE THE TABLE IS THE FIRST THING IN THE PANEL.
   The shell's lead-in is the platform's 10px (§18), so a band on top of it
   would pay the standoff twice. Anything above the table — a view switch, a
   bulk bar that is showing — is "something above", and the band comes back
   under it. A HIDDEN bulk bar is above nothing, so the second selector names
   it; the wrap's own top rule goes the same way under a bar. */
.po-hub ~ .tab-shell > .card > .table-wrap:first-child .data-table thead th,
.po-hub ~ .tab-shell > .card > [hidden]:first-child + .table-wrap .data-table thead th { border-top: 0; }
.po-hub ~ .tab-shell > .card .po-bulk + .table-wrap { border-top: 0; }
.po-hub ~ .tab-shell > .card .po-bulk { margin-bottom: 10px; }

/* The view switch (.po-viewbar) is shared with Orders · Shipments and lives in app.css. */

/* ---------- Register tables ------------------------------------------------------
   Every register is a `.data-table` whose columns take percentage shares of
   the table under `table-layout: fixed`, declared in the PAGE's stylesheet.
   What they share is here. A row is the way into the record, so the cursor
   says so. The bar between a number and a person on the sub-line
   ("PO-2026-0223 | E. Costa") is joinery, drawn in the border ink. The check
   column centres its box and its row mark. A status cell may carry a badge
   AND a flag word ("Late 7 Days"), so it wraps and lets the word drop under
   the badge, read whichever line it lands on. */
.po-table tbody tr { cursor: pointer; }
.po-table .sub .sep { margin: 0 6px; color: var(--color-border-strong); }
.po-table th.col-check,
.po-table td.col-check { text-align: center; }
.po-table tbody td.col-check::after { background: var(--row-mark-center); }
.po-table td.col-status { white-space: normal; line-height: 1.9; }
.po-table td.col-status .badge { vertical-align: middle; }
.po-table td.col-status .po-reading { font-size: 12px; vertical-align: middle; }
.po-table td a { color: var(--color-primary-600); text-decoration: none; }
.po-table td a:hover { color: var(--color-primary-700); }
/* The row checkbox: the primary as its accent, sized to read as a control. */
.po-check {
  width: 16px; height: 16px; margin: 0; vertical-align: middle;
  accent-color: var(--color-primary); cursor: pointer;
}

/* ---------- The bulk bar ---------------------------------------------------------
   Appears above a register the moment a row is checked and goes when the last
   one is cleared. The count leads — number first, then the word (memory.md
   §6) — and the actions follow as outline buttons. It stands on the control
   ground because it is a thing inside a white panel (§13). `[hidden]` is
   restated because the bar sets its own `display`. */
.po-bulk {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 8px 12px;
  background: var(--color-control);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius);
}
.po-bulk[hidden] { display: none; }
.po-bulk__count { font-size: 13px; color: var(--color-text-muted); white-space: nowrap; margin-right: 6px; }
.po-bulk__count strong { color: var(--color-text); font-weight: 600; font-variant-numeric: tabular-nums; }
.po-bulk__clear { margin-left: auto; }

/* ---------- A group header row ----------------------------------------------------
   A supplier group on Reorder, a material group on a PO's Lines: one row that
   spans the table, its label in 12px 600 and a muted subtotal reading after
   it, on the control ground so the groups read as sections of one list. The
   row mark under it goes: a band is not a row. Markup:
     <tr class="po-group-row"><td colspan="9"><span class="po-group-row__label">
       Marmi Apuani</span><span class="po-group-row__sub">2 lines · …</span></td></tr> */
.data-table tbody tr.po-group-row td {
  background: var(--color-control);
  padding-top: 7px; padding-bottom: 7px;
  cursor: default;
}
.data-table tbody tr.po-group-row td::after { content: none; }
.data-table tbody tr.po-group-row:hover td { background: var(--color-control); }
.po-group-row__label { font-size: 12px; font-weight: 600; color: var(--color-text); margin-right: 10px; }
.po-group-row__label a { color: inherit; }
.po-group-row__sub { font-size: 12px; color: var(--color-text-muted); }

/* ---------- Readings: words, not chips ----------------------------------------------
   A supplier type, a country, a mode, an incoterm, an age, a count: each is a
   WORD in the row's own type, and several are one line joined by `·`, drawn
   by CSS before every child but the first so no page types a stray dot.
   Nothing here has a fill — a filled mini-panel is a badge, and a badge's
   colour means a state (memory.md §19). Colour and weight go to the urgent
   reading alone: danger ink for the late, the past last free day, the overdue
   bill and the short-received; warn ink for the one due; success ink for the
   one done. `.po-progress` is the same shape under its own name.

   THE DOT TRAILS THE WORD IT FOLLOWS (an `::after` on every child but the
   last), as orders.css draws it. The two shapes are the same row while it
   fits; when a register cell wraps, a leading dot would travel down and open
   the second line with punctuation ("· Unpaid"), where a trailing one stays at
   the end of the first line, where a list is expected to break. */
.po-reading,
.po-progress {
  display: inline-flex; flex-wrap: wrap; align-items: center;
  row-gap: 2px; max-width: 100%;
  font-size: 13px; color: var(--color-text);
}
.po-reading > *,
.po-progress > * { display: inline-flex; align-items: center; gap: 5px; }
.po-reading > *:not(:last-child)::after,
.po-progress > *:not(:last-child)::after {
  content: "·";
  margin: 0 6px 0 1px;
  color: var(--color-text-subtle);
  font-weight: 400;
}
.po-reading i,
.po-reading svg,
.po-progress svg { width: 14px; height: 14px; flex: none; color: var(--color-text-muted); }
.po-reading .dot-status,
.po-progress .dot-status { flex: none; }
.po-reading .is-urgent,
.po-reading.is-urgent { color: var(--color-danger-ink); font-weight: 600; }
.po-reading .is-warn,
.po-reading.is-warn { color: var(--color-warn-ink); }
.po-reading .is-ok,
.po-reading.is-ok { color: var(--color-success-ink); }
.po-reading .is-urgent svg,
.po-reading.is-urgent svg,
.po-reading .is-warn svg,
.po-reading.is-warn svg { color: currentColor; }
/* Received · Billed · Paid: each a `.dot-status` in the state's colour and a
   word. One reading does not break inside itself; the three wrap as wholes. */
.po-progress > * { white-space: nowrap; }

/* A category word — supplier type, country, incoterm, currency, cost type,
   grade, spread basis — is grey, always (§19). Never a badge. */
.po-kind { color: var(--color-text-muted); }

/* The mode word with its lucide icon (ship · truck · plane). One word, never
   broken: "Container 20 ft" over two lines is two readings. */
.po-mode { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.po-mode svg { width: 14px; height: 14px; flex: none; color: var(--color-text-muted); }

/* The Vava-network reading: `link-2` and one of three phrases. Linked is a
   live state (success ink); a request sent is a wait (warn ink); not on Vava
   is just a fact, in muted grey. */
.po-linked {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--color-text-muted); white-space: nowrap;
}
.po-linked svg { width: 14px; height: 14px; flex: none; color: currentColor; }
.po-linked.is-on      { color: var(--color-success-ink); }
.po-linked.is-pending { color: var(--color-warn-ink); }

/* Tags: free words with the `tag` icon at 12px, muted, wrapping — "For
   ORD-2026-0034", "Consignment · Stone Source Distributors". A tag naming a
   record is a plain link to it. */
.po-tags { display: flex; flex-wrap: wrap; gap: 2px 10px; margin-top: 2px; }
.po-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; color: var(--color-text-muted); line-height: 1.5;
}
.po-tag svg { width: 12px; height: 12px; flex: none; color: var(--color-text-subtle); }
.po-tag a { color: var(--color-primary-600); text-decoration: none; white-space: nowrap; }
.po-tag a:hover { color: var(--color-primary-700); }

/* An ETA that moved: the first-promised date muted and struck through, an
   arrow, the current date, and the slip as a word — late in danger ink,
   early in success ink. Read it as one fact; it does not break. */
.po-eta { display: inline-flex; align-items: center; gap: 5px; flex-wrap: wrap; font-variant-numeric: tabular-nums; }
.po-eta s,
.po-eta del { color: var(--color-text-subtle); text-decoration-color: var(--color-text-subtle); }
.po-eta svg { width: 12px; height: 12px; flex: none; color: var(--color-text-subtle); }
.po-eta__late { color: var(--color-danger-ink); font-weight: 600; white-space: nowrap; }
.po-eta__early { color: var(--color-success-ink); font-weight: 600; white-space: nowrap; }

/* The last free day at the port, with the `hourglass`. Urgent when 3 days or
   fewer are left (the tenant's alert window). */
.po-lfd { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; color: var(--color-text-muted); }
.po-lfd svg { width: 14px; height: 14px; flex: none; }
.po-lfd.is-urgent { color: var(--color-danger-ink); font-weight: 600; }

/* Two currencies: the main line in the supplier's own (its code or symbol
   written by the page, never by CSS), and under it the base-currency figure
   with the rate it was locked at, 11px muted — "$89,952.94 at 1.10". */
.po-fx { display: inline-flex; flex-direction: column; line-height: 1.35; font-variant-numeric: tabular-nums; }
.po-fx__base { font-size: 11px; color: var(--color-text-muted); white-space: nowrap; }

/* What a user WITHOUT the purchase-costs permission sees where a buying figure
   would sit: the lock and the sentence, muted, 12px. It replaces the figure;
   it never sits beside it. */
.po-perm {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--color-text-muted); white-space: normal;
}
.po-perm svg { width: 13px; height: 13px; flex: none; }

/* A help mark after a label, with its explanation in `title`. */
.po-help {
  display: inline-flex; vertical-align: middle; margin-left: 4px;
  color: var(--color-text-subtle); cursor: help;
}
.po-help svg { width: 14px; height: 14px; }

/* ---------- Detail header ----------------------------------------------------------
   `.page-header.po-head`: the identity column on the left (crumb, h1, badge
   row, settable fields) takes a zero flex-basis so a long field row wraps
   inside it and the page actions keep their place top-right.
     .po-head__crumb   "Purchase Orders" back to the register
     .po-head__title   the h1 and the status badge, centred on each other
     .po-head__badges  the readings beside the identity (Vava link, tags)
   The status badge is scaled to stand as tall as the 22px number. */
.po-head > :first-child { flex: 1 1 0; min-width: 0; }
.po-head__crumb {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 4px; font-size: 12px; color: var(--color-text-subtle);
}
.po-head__crumb a { color: var(--color-text-muted); text-decoration: none; }
.po-head__crumb a:hover { color: var(--color-primary-700); }
.po-head__crumb svg { width: 13px; height: 13px; }
.po-head__title { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; }
.po-head__title .page-title { display: inline-flex; align-items: baseline; flex-wrap: wrap; }
.po-head__title .badge { font-size: 13px; padding: 4px 11px; }
.po-head__badges { display: flex; align-items: center; gap: 6px 14px; flex-wrap: wrap; margin-top: 6px; font-size: 12px; }
.po-head__badges .po-reading { font-size: 12px; }
.po-head .page-actions { flex-wrap: wrap; }

/* ---------- Settable fields ---------------------------------------------------------
   A row of fields that read as text until you reach for them: 12px, a 12px
   icon, a pencil hint always there in the lightest ink, and on hover the
   control ground (§13). `--static` is a field that is a link rather than a
   form (it opens another page); `--unset` is drawn in danger until set. The
   10px qualifier under a value ("Supplier Default") is the floor (§4).
     <button class="po-field"><i data-lucide="anchor"></i><span>
       <span class="po-field__v">FOB La Spezia</span>
       <span class="po-field__sub">Supplier Default</span></span>
       <i data-lucide="pencil" class="po-field__edit"></i></button> */
.po-fields { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 4px 6px; margin-top: 8px; }
.po-field {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid transparent; border-radius: var(--radius);
  background: none; cursor: pointer; text-align: left;
  padding: 3px 7px; margin-left: -7px; margin-right: 6px;
  font: inherit; font-size: 12px; color: var(--color-text); text-decoration: none;
  transition: background 120ms, border-color 120ms;
}
.po-field:hover { background: var(--color-control); border-color: var(--color-control-border); color: var(--color-text); }
.po-field svg { width: 12px; height: 12px; flex: none; color: var(--color-text-subtle); }
.po-field__k { color: var(--color-text-muted); }
.po-field__v { font-weight: 500; }
.po-field > span { display: inline-flex; flex-direction: column; line-height: 1.35; }
.po-field__sub { font-size: 10px; font-weight: 400; color: var(--color-text-subtle); }
.po-field__edit { opacity: .8; }
.po-field--static .po-field__v { color: var(--color-primary-600); }
.po-field--unset,
.po-field--unset .po-field__v,
.po-field--unset svg { color: var(--color-danger-ink); }
.po-field--unset { border-color: var(--color-danger); }

/* ---------- The status path -------------------------------------------------------------
   A row of steps: done in success, the current one in warn ink and 600 with a
   3px warn-50 ring, the rest muted. Each step is a WORD with a dot before it
   and a hairline on to the next, so it reads as the tenant's statuses and not
   as a progress bar. `--container`, `--claim` and `--rfq` change WHICH steps a
   page writes, never how one is drawn; `.is-exit` is a side exit taken
   (Cancelled, Declined). `.po-next` is the "Next: …" word after the path;
   `.po-path-row` holds the two on one line. */
.po-path-row {
  display: flex; align-items: center; gap: 8px 18px; flex-wrap: wrap;
  margin-bottom: var(--page-gap);
}
.po-path-row .po-path { flex: 1 1 auto; min-width: 0; }
.po-path {
  display: flex; flex-wrap: wrap; align-items: center; row-gap: 6px;
  margin: 0; padding: 0; list-style: none;
  font-size: 12px; color: var(--color-text-subtle);
}
.po-path__step { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.po-path__step::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--color-border-strong);
}
.po-path__step:not(:last-child)::after {
  content: ""; width: 16px; height: 1px; flex: none; margin: 0 7px 0 5px;
  background: var(--color-border-strong);
}
.po-path__step.is-done { color: var(--color-success-ink); }
.po-path__step.is-done::before,
.po-path__step.is-done::after { background: var(--color-success); }
.po-path__step.is-current { color: var(--color-warn-ink); font-weight: 600; }
.po-path__step.is-current::before { background: var(--color-warn); box-shadow: 0 0 0 3px var(--color-warn-50); }
.po-path__step.is-exit { color: var(--color-danger-ink); }
.po-path__step.is-exit::before { background: var(--color-danger); }
/* `.po-path--container`, `--claim`, `--rfq` carry no rule of their own. */
.po-next {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--color-text-muted);
}
.po-next svg { width: 14px; height: 14px; flex: none; }
.po-next strong { color: var(--color-warn-ink); font-weight: 600; }

/* ---------- The figure bar ----------------------------------------------------------------
   One white box, a hairline between readings; each reading is the number on
   its own line (18px, tabular) with its word under it, kept tight (memory.md
   §6). `.s` is an 11px sub-line ("Fri Aug 7"). `--ok`, `--due`, `--bad` colour
   the value's ink only. `.po-stat-line` puts value and word on one line where
   a reading is short ("28 slabs + 8 crates"). `.po-stat--fill` takes the slack
   and holds a `.po-fill--compact`. 25px under it: the standoff every box above
   an attached strip takes. */
.po-stats {
  display: flex; flex-wrap: wrap; align-items: stretch;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  margin-bottom: 25px;
  overflow: hidden;
}
.po-stat {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 1px;
  padding: 8px 14px;
  box-shadow: -1px 0 0 0 var(--color-border);
}
.po-stat .v { font-size: 18px; font-weight: 600; letter-spacing: -0.01em; color: var(--color-text); font-variant-numeric: tabular-nums; line-height: 1.2; }
.po-stat .l { font-size: 12px; color: var(--color-text-muted); white-space: nowrap; }
.po-stat .s { font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.po-stat--ok .v  { color: var(--color-success-ink); }
.po-stat--due .v { color: var(--color-warn-ink); }
.po-stat--bad .v { color: var(--color-danger-ink); }
.po-stat-line { display: inline-flex; align-items: baseline; gap: 6px; }
.po-stat--fill { flex: 1 1 260px; min-width: 0; }
.po-stat--fill .po-fill { max-width: none; width: 100%; }

/* ---------- Key–value grid ------------------------------------------------------------------
   Label right-aligned in the muted ink, value left-aligned, an 8px gap: tight
   at the centre, never spread. Works on a <dl> (dt / dd) and on a div grid
   (__k / __v) alike. One column under 480 (below). */
.po-kv {
  display: grid; grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 8px; row-gap: 6px; align-items: baseline;
  margin: 0;
}
.po-kv dt,
.po-kv__k { margin: 0; text-align: right; font-size: 12px; color: var(--color-text-muted); white-space: nowrap; }
.po-kv dd,
.po-kv__v { margin: 0; min-width: 0; font-size: 13px; color: var(--color-text); }

/* ---------- A subsection inside the one panel ----------------------------------------------
   A detail page is ONE card with internal dividers (owner preference). Each
   subsection is a heading row — a 14px Title Case heading, a muted reading
   after it, the actions on the right — and a body; the 1px border divides one
   from the next. */
.po-sec { padding: 16px 0; }
.po-sec:first-child { padding-top: 0; }
.po-sec:last-child { padding-bottom: 0; }
.po-sec + .po-sec { border-top: 1px solid var(--color-border); }
.po-sec__h {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px;
  margin-bottom: 12px;
}
.po-sec__h h3,
.po-sec__h h4 { margin: 0; font-size: 14px; font-weight: 600; color: var(--color-text); }
.po-sec__h .subtle,
.po-sec__h .po-reading { font-size: 12px; }
.po-sec__acts { margin-left: auto; display: inline-flex; flex-wrap: wrap; gap: 6px; }
.po-sec__body { min-width: 0; }

/* ---------- Timeline ---------------------------------------------------------------------------
   Activity, milestones and supplier updates: the time in 11px muted on the
   left, a 6px dot in the state's colour, the event in 13px. One grid so the
   dots make a column whatever the width of the times; an <li> spreads its
   cells with `display: contents`. `__est` is the muted "est." before an
   estimated time. `__acts` is an optional row of buttons under an event. */
.po-timeline {
  display: grid; grid-template-columns: max-content 6px minmax(0, 1fr);
  column-gap: 10px; row-gap: 12px; align-items: baseline;
  margin: 0; padding: 0; list-style: none;
}
.po-timeline > li { display: contents; }
.po-timeline__time {
  font-size: 11px; color: var(--color-text-muted); text-align: right;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.po-timeline__est { color: var(--color-text-subtle); font-style: italic; margin-right: 3px; }
/* The dot sits level with the event's FIRST line (13px at 1.45), not at the
   middle of an event that carries photos or buttons under it. */
.po-timeline__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-border-strong); align-self: start; margin-top: 7px; }
.po-timeline__dot.ok   { background: var(--color-success); }
.po-timeline__dot.warn { background: var(--color-warn); }
.po-timeline__dot.bad  { background: var(--color-danger); }
.po-timeline__dot.new  { background: var(--color-info); }
.po-timeline__text { min-width: 0; font-size: 13px; color: var(--color-text); line-height: 1.45; }
.po-timeline__text .who { font-size: 12px; color: var(--color-text-muted); }
.po-timeline__acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

/* ---------- A document row ----------------------------------------------------------------------
   The PDF mark (img/ExportPDF.png at 24px), the name, its version, who sees it
   ("Sent to Supplier" / "Internal" / "From Supplier") as a grey word, and the
   actions on the right. Rows divide with the border hairline. */
.po-doc {
  display: flex; align-items: center; gap: 6px 10px; flex-wrap: wrap;
  padding: 8px 0; border-bottom: 1px solid var(--color-border);
  font-size: 13px;
}
.po-doc:last-child { border-bottom: 0; }
.po-doc__ico { width: 24px; height: 24px; flex: none; object-fit: contain; }
.po-doc__name { font-weight: 500; color: var(--color-text); min-width: 0; }
.po-doc__ver { font-size: 12px; color: var(--color-text-muted); white-space: nowrap; }
.po-doc__vis { font-size: 12px; color: var(--color-text-muted); white-space: nowrap; }
.po-doc__acts { margin-left: auto; display: inline-flex; gap: 6px; flex: none; }
.po-doc__acts .btn-sm svg { width: 14px; height: 14px; }

/* ---------- Photos --------------------------------------------------------------------------------
   Thumbnails from img/products/ (72px; `--lg` 120px for receiving and claims)
   in a grid that packs as many as fit. A trailing "+20" cell for the ones not
   drawn, and the house no-photo slot for a slab without one, stand on the
   control ground. */
.po-photos { display: grid; grid-template-columns: repeat(auto-fill, 72px); gap: 8px; }
.po-photos img,
.po-photos__more,
.po-photos__none {
  width: 72px; height: 72px; display: block; object-fit: cover;
  border-radius: var(--radius); border: 1px solid var(--color-border);
}
.po-photos__more,
.po-photos__none {
  display: flex; align-items: center; justify-content: center;
  background: var(--color-control); border-color: var(--color-control-border);
  color: var(--color-text-muted); font: inherit; font-size: 12px; font-weight: 500;
}
.po-photos__more { cursor: pointer; }
.po-photos__none svg { width: 20px; height: 20px; color: var(--color-text-subtle); }
.po-photos--lg { grid-template-columns: repeat(auto-fill, 120px); }
.po-photos--lg img,
.po-photos--lg .po-photos__more,
.po-photos--lg .po-photos__none { width: 120px; height: 120px; }

/* ---------- Slab tables -----------------------------------------------------------------------------
   `.data-table.po-slabs`: the compact slab list (packing list, receiving,
   claims). 12px cells, the slab number tabular and 600, and the result as a
   WORD coloured by its family — never a chip. */
.data-table.po-slabs tbody td { font-size: 12px; padding-top: 7px; padding-bottom: 7px; }
.po-slab-id { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--color-text); white-space: nowrap; }
.po-slabs .is-ok   { color: var(--color-success-ink); }
.po-slabs .is-warn { color: var(--color-warn-ink); }
.po-slabs .is-bad  { color: var(--color-danger-ink); font-weight: 600; }

/* ---------- The supplier thread ------------------------------------------------------------------------
   One thread per PO (also per claim). Each message is a block: who, which
   side ("Supplier" / "Us" / "Internal"), when, the body, any files. Every
   message is a box inside a white panel, so it stands on the control ground
   (memory.md §13: never a white box on a white card). An internal note adds a
   3px warn rule on its left edge and says "Internal · hidden from supplier",
   so it is told apart by a mark and a word, never by a second ground.
   `__suggest` is a suggested update read from a supplier's reply, with
   Apply / Ignore; nothing applies on its own. `__composer` holds the reply
   box and the two-sided Supplier Sees It / Internal Only choice. */
.po-thread { display: flex; flex-direction: column; gap: 10px; }
.po-thread__msg {
  padding: 10px 12px;
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius);
  background: var(--color-control);
}
.po-thread__msg--internal { border-left: 3px solid var(--color-warn); padding-left: 10px; }
.po-thread__head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; margin-bottom: 4px; }
.po-thread__who { font-size: 13px; font-weight: 600; color: var(--color-text); }
.po-thread__side { font-size: 11px; color: var(--color-text-muted); }
.po-thread__time { font-size: 11px; color: var(--color-text-subtle); margin-left: auto; white-space: nowrap; font-variant-numeric: tabular-nums; }
.po-thread__body { font-size: 13px; color: var(--color-text); line-height: 1.5; margin: 0; }
.po-thread__files { display: flex; flex-wrap: wrap; gap: 6px 12px; margin-top: 6px; font-size: 12px; }
.po-thread__files a { display: inline-flex; align-items: center; gap: 4px; color: var(--color-primary-600); text-decoration: none; }
.po-thread__files svg { width: 13px; height: 13px; }
.po-thread__suggest {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
  margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--color-border-strong);
  font-size: 12px; color: var(--color-text-muted);
}
.po-thread__suggest svg { width: 14px; height: 14px; flex: none; color: var(--color-info); }
.po-thread__suggest strong { color: var(--color-text); font-weight: 600; }
.po-thread__suggest .btn { margin-left: 2px; }
.po-thread__composer { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.po-thread__composer .textarea { min-height: 72px; }
.po-thread__composer-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; }
.po-thread__composer-row .btn-primary { margin-left: auto; }

/* ---------- Offers side by side -------------------------------------------------------------------------
   `.po-compare` wraps a <table>: one column per supplier (`__head`), one row
   per basis (`__label` on the row's <th>), cells `__cell`. The best landed
   figure is success ink and 600 with its "Lowest Landed" word; a supplier
   that did not answer is muted "No Reply". `__award` is the award row. The
   wrapper scrolls sideways at 768 instead of crushing the columns. */
.po-compare { overflow-x: auto; }
.po-compare table { width: 100%; border-collapse: collapse; font-size: 13px; }
.po-compare th,
.po-compare td { padding: 8px 12px; border-bottom: 1px solid var(--color-border); text-align: left; vertical-align: top; }
.po-compare__head { font-size: 13px; font-weight: 600; color: var(--color-text); background: var(--color-control); }
.po-compare__head .sub { display: block; font-size: 11px; font-weight: 400; color: var(--color-text-muted); }
.po-compare__label { font-size: 12px; font-weight: 500; color: var(--color-text-muted); white-space: nowrap; }
.po-compare__cell { font-variant-numeric: tabular-nums; }
.po-compare__cell .sub { display: block; font-size: 11px; color: var(--color-text-muted); }
.po-compare .is-best { color: var(--color-success-ink); font-weight: 600; }
.po-compare .is-noreply { color: var(--color-text-subtle); }
.po-compare__award td,
.po-compare__award th { border-bottom: 0; background: var(--color-control); }

/* ---------- The three-way match --------------------------------------------------------------------------
   Packing List · Receipt · Bill, line by line: the line name, the three
   columns (count and area), and the difference. A short line is danger ink,
   an over one warn ink, a clean one success ink. `__slabs` is the expandable
   per-slab list under a line (a <details>). */
.po-match { display: flex; flex-direction: column; font-size: 13px; }
.po-match__line {
  display: grid;
  grid-template-columns: minmax(150px, 1.4fr) repeat(3, minmax(90px, 1fr)) minmax(120px, 1.1fr);
  gap: 4px 12px; align-items: baseline;
  padding: 9px 0; border-bottom: 1px solid var(--color-border);
}
.po-match__line--head {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--color-text-muted); padding-top: 0;
}
.po-match__col { font-variant-numeric: tabular-nums; min-width: 0; }
.po-match__col .sub { display: block; font-size: 11px; color: var(--color-text-muted); }
.po-match__diff { font-weight: 600; }
.po-match .is-short { color: var(--color-danger-ink); }
.po-match .is-over  { color: var(--color-warn-ink); }
.po-match .is-ok    { color: var(--color-success-ink); }
.po-match__slabs { grid-column: 1 / -1; font-size: 12px; color: var(--color-text-muted); }
.po-match__slabs summary { cursor: pointer; color: var(--color-primary-600); }

/* ---------- Landed cost table helpers ------------------------------------------------------------------------
   On a `.data-table.po-cost`: the total row in 600 with a rule above it, an
   estimate muted where an actual figure exists beside it, and an 11px note
   under the table. */
.po-cost tr.po-cost__total td { font-weight: 600; border-top: 1px solid var(--color-border-strong); }
.po-cost__est { color: var(--color-text-subtle); }
.po-cost__note { margin: 8px 0 0; font-size: 11px; color: var(--color-text-subtle); }

/* ---------- Container fill ---------------------------------------------------------------------------------
   Stone fills a box by weight long before it fills it by volume, so a fill is
   never one bar: WEIGHT FIRST, VOLUME SECOND, each a bar with its figures
   beside it, and one line naming which closes first. The bar is an inline
   SVG whose <rect> width IS the percentage:
     <div class="po-fill">
       <span class="po-fill__label">Weight</span>
       <svg class="po-fill__bar" viewBox="0 0 100 6" preserveAspectRatio="none" aria-hidden="true">
         <rect class="po-fill__level warn" width="77.7" height="6"></rect></svg>
       <span class="po-fill__fig">16,700 / 21,500 kg <span class="po-fill__pct">77.7%</span></span>
       … the Volume row the same …
       <span class="po-fill__closes"><strong>Weight closes first</strong> · 20 ft</span>
     </div>
   The track takes the control ground (§13). `--compact` sizes it for a table
   cell or the figure bar. */
.po-fill {
  display: grid; grid-template-columns: max-content minmax(70px, 1fr) max-content;
  column-gap: 10px; row-gap: 6px; align-items: center;
  max-width: 440px;
  font-size: 12px; color: var(--color-text-muted);
}
.po-fill__label { text-align: right; }
.po-fill__bar {
  display: block; width: 100%; height: 6px;
  border-radius: 5px; overflow: hidden;
  background: var(--color-control);
}
.po-fill__level { fill: var(--color-success); }
.po-fill__level.warn   { fill: var(--color-warn); }
.po-fill__level.danger { fill: var(--color-danger); }
.po-fill__fig { color: var(--color-text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.po-fill__pct { font-weight: 600; margin-left: 4px; }
.po-fill__closes { grid-column: 1 / -1; font-size: 11px; color: var(--color-text-muted); }
.po-fill__closes strong { color: var(--color-warn-ink); font-weight: 600; }
.po-fill--compact { max-width: 260px; column-gap: 8px; row-gap: 3px; font-size: 11px; }
.po-fill--compact .po-fill__bar { height: 5px; }

/* ---------- Choice rows in dialogs ----------------------------------------------------------------------------
   Destination, start-from, settlement, supplier pick: each choice is a row on
   the control ground — an icon, the name, a muted meta line, a check mark
   that shows only once chosen. ALL START UNCHOSEN (show the options, never
   preselect one); `.is-selected` is set by the user's click. `.is-off` is a
   choice that cannot be taken yet, with its reason in the meta line. */
.po-pick { display: flex; flex-direction: column; gap: 6px; }
.po-pick-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 10px 12px;
  background: var(--color-control); border: 1px solid var(--color-control-border);
  border-radius: var(--radius);
  font: inherit; text-align: left; color: var(--color-text); cursor: pointer;
  transition: border-color 120ms, background 120ms;
}
.po-pick-row:hover { border-color: var(--color-border-strong); background: var(--color-surface); }
.po-pick-row__ico { width: 18px; height: 18px; flex: none; color: var(--color-text-muted); }
.po-pick-row__body { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.po-pick-row__name { font-size: 13px; font-weight: 600; }
.po-pick-row__meta { font-size: 12px; color: var(--color-text-muted); }
.po-pick-row__check { width: 16px; height: 16px; flex: none; color: var(--color-primary); visibility: hidden; }
.po-pick-row.is-selected { border-color: var(--color-primary); background: var(--color-surface); box-shadow: 0 0 0 1px var(--color-primary); }
.po-pick-row.is-selected .po-pick-row__check { visibility: visible; }
.po-pick-row.is-off { opacity: .6; cursor: not-allowed; }
.po-pick-row.is-off:hover { background: var(--color-control); border-color: var(--color-control-border); }

/* ---------- A two-sided choice ------------------------------------------------------------------------------
   "Save for: Me | Miami Yard", "Supplier Sees It | Internal Only", "Put Away
   Now | Put Away Later": a yes/no is a switch with BOTH sides labelled, the
   side in force told by colour and weight — never boxed, never underlined.
   The one place the switch does not lead its label (§5): it stands between
   its two answers. */
.po-sides { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; }
.po-sides__lead { font-size: 12px; color: var(--color-text-muted); margin-right: 2px; }
.po-sides__opt {
  font-size: 12px; font-weight: 500; color: var(--color-text-muted);
  white-space: nowrap; cursor: pointer;
  transition: color 120ms;
}
.po-sides__opt.is-active { color: var(--color-text); font-weight: 600; }

/* ---------- Empty state ------------------------------------------------------------------------------------
   An icon, one sentence, the one action that would change it, on the control
   ground with a dashed edge. */
.po-empty {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 24px 16px; text-align: center;
  font-size: 13px; color: var(--color-text-muted);
  background: var(--color-control); border: 1px dashed var(--color-control-border);
  border-radius: var(--radius);
}
.po-empty > svg { width: 28px; height: 28px; color: var(--color-text-subtle); }
.po-empty p { margin: 0; max-width: 520px; }

/* ---------- The vessel chart --------------------------------------------------------------------------------
   A STATIC inline SVG in the page (offline at trade shows: never an iframe,
   never tiles): sea on the control ground, land white with a hairline coast,
   the route ahead dashed in the primary and the sailed part solid, ports as
   5px dots, the position as a warn dot with a ring, 11px labels. 300px tall,
   220px under 768. The milestone timeline beside it carries the same facts. */
.po-map {
  height: 300px; overflow: hidden;
  border: 1px solid var(--color-border); border-radius: var(--radius);
  background: var(--color-control);
}
.po-map svg { display: block; width: 100%; height: 100%; }
.po-map__sea { fill: var(--color-control); }
.po-map__land { fill: var(--color-surface); stroke: var(--color-border-strong); stroke-width: 1; }
.po-map__route { fill: none; stroke: var(--color-primary); stroke-width: 2; stroke-dasharray: 6 5; }
.po-map__done { fill: none; stroke: var(--color-primary); stroke-width: 2.5; }
.po-map__port { fill: var(--color-text-muted); }
.po-map__pos { fill: var(--color-warn); stroke: var(--color-warn-50); stroke-width: 5; paint-order: stroke; }
.po-map__label { fill: var(--color-text-muted); font-size: 11px; font-family: 'Hanken Grotesk', sans-serif; }
.po-map__legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 6px; font-size: 11px; color: var(--color-text-subtle); }

/* ---------- Page-gear dialogs ----------------------------------------------------------------------------------
   Manage KPIs, Manage Columns and Saved Views open from the gear on every
   register, so their pieces are shared (orders.css's shapes, `po-` names).
   MANAGE KPIS adds one answer to the house reorder row: how wide the tile
   draws (¼ ⅓ ½), a select sized to its glyphs (§9) standing straight after
   its label (§16). */
.po-kpi-row .switch-field { flex: none; }
.po-kpi-width {
  width: auto; flex: none;
  padding: 4px 26px 4px 9px; font-size: 12px;
  background-position: right 8px center;
}
/* MANAGE COLUMNS: the identity column cannot be hidden, so its row is locked. */
.po-cols .reorder-item.is-locked .reorder-grip { opacity: .35; cursor: default; }
.po-cols .reorder-item.is-locked .switch { opacity: .55; pointer-events: none; }
.po-col-note { font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.po-save-for { margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--color-border); }
/* A line of explanation under a dialog's control, in the hint type. */
.po-dialog-note { margin: 10px 0 0; font-size: 12px; color: var(--color-text-subtle); }
/* SAVED VIEWS: each view a row on the control ground — the mark, the name with
   what it narrows to, who it is saved for, and Apply. */
.po-views { display: flex; flex-direction: column; gap: 6px; }
.po-view {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 11px;
  background: var(--color-control); border: 1px solid var(--color-control-border);
  border-radius: var(--radius);
}
.po-view .cell-stack { flex: 1; min-width: 0; }
.po-view__ico { width: 16px; height: 16px; flex: none; color: var(--color-text-subtle); }
.po-view__who { font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.po-view-save { margin-top: 16px; }
.po-view-save__row { align-items: stretch; }
.po-view-save__row .btn { flex: none; }

/* ---------- Narrow screens -------------------------------------------------------------------------------------
   Touch targets grow to the 44px floor; the key–value grid stacks its label
   over its value; the figure bar becomes a grid; the match and compare grids
   scroll inside themselves rather than the page. */
@media (max-width: 768px) {
  .po-bulk .btn,
  .po-doc__acts .btn,
  .po-sec__acts .btn,
  .po-timeline__acts .btn { min-height: 44px; }
  .po-viewbar__btn { min-height: 36px; }
  .po-check { width: 18px; height: 18px; }
  .po-head > :first-child { flex-basis: 100%; }
  .po-field { min-height: 32px; }
  .po-kv { grid-template-columns: 1fr; row-gap: 2px; }
  .po-kv dt,
  .po-kv__k { text-align: left; }
  .po-kv dd + dt,
  .po-kv__v + .po-kv__k { margin-top: 8px; }
  .po-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .po-stat { box-shadow: -1px -1px 0 0 var(--color-border); }
  .po-stat--fill { grid-column: 1 / -1; }
  .po-fill { max-width: none; }
  .po-match { overflow-x: auto; }
  .po-match__line { min-width: 620px; }
  .po-sec__acts { margin-left: 0; flex-basis: 100%; }
  .po-path-row .po-path { flex-basis: 100%; }
  .po-map { height: 220px; }
}
@media (max-width: 480px) {
  .po-bulk { gap: 6px; }
  .po-bulk__count { flex-basis: 100%; margin-right: 0; }
  .po-bulk__clear { margin-left: 0; }
  .po-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .po-stat .l,
  .po-stat .s { white-space: normal; }
  .po-doc__acts { margin-left: 0; flex-basis: 100%; }
  .po-thread__time { margin-left: 0; }
  .po-view { flex-wrap: wrap; }
  .po-view__who { flex-basis: 100%; padding-left: 26px; }
  .po-timeline { column-gap: 8px; }
  .po-fill { column-gap: 6px; }
}
