/* ==========================================================================
   Orders — the module's shared stylesheet
   (orders.html, order.html, deliveries.html,
    order-shipment.html, orders-pickups.html, orders-payments.html,
    orders-invoices.html, order-invoice.html, orders-claims.html,
    order-claim.html, orders-workflow.html, orders-documents.html,
    orders-template-editor.html, settings-orders.html, order-share.html)

   Spec: build/pages.md → "Shared stylesheet contract"

   One module, sixteen pages, one vocabulary. Everything here is a thing more
   than one Orders page says — a reading written as words, the side a record
   trades on, the mode it ships by, a hold, the fill of a container, the path a
   status walks — and the `ord-` prefix names that vocabulary rather than any
   one page. What belongs to a single page (its register's column shares, how
   it folds on a phone) lives in that page's own `css/pages/<page>.css`.

   TOKENS ONLY, LIGHT THEME ONLY. Every colour is a `var(--color-…)` read off
   app.css, so the two 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 side, a mode, a client
   type or a count is grey text joined by `·`.

   Nothing here depends on orders.html's markup. A page that uses a class uses
   it on its own structure; the one structural assumption is the hub shell the
   brief gives every register — `.tabs--attached.ord-hub` followed by a
   `.tab-shell` holding one `.card` — and the rules that make that join are
   scoped to exactly that pair.
   ========================================================================== */

/* ---------- Shell helpers ---------------------------------------------------
   quotes.html, the shell every Orders page copies, sizes six things inline:
   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. An inline `style` is
   forbidden on these pages (memory.md §14) and the audit counts them, so each
   of those is a class here — once, for all sixteen pages — and the shell
   carries the class where quotes.html carried the style. `.page-settings`
   already has its `position: relative` and its 232px menu in app.css, so the
   gear needs nothing of its own. */
.ord-rel { position: relative; }
.ord-menu--wide { min-width: 328px; }
.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); }
/* Lucide ships icons at 24px. In a 13px menu row that reads as an icon list
   with labels attached rather than a menu; 15px puts the icon under the cap
   height — the number app.css gives `.page-settings .dropdown-item svg`, said
   here for the menus that rule does not reach (the notifications bell, a row
   menu, a dialog's own list). Lucide copies the <i>'s class onto the <svg> it
   draws in its place, so the class goes on the <i>. */
.ord-menu-ico { width: 15px; height: 15px; flex: none; }

/* ---------- The hub strip ---------------------------------------------------
   Six 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. app.css styles the class, not the element, and
   the two things an anchor brings of its own are an underline and the link
   colour; `.tab` already outranks `a` on colour, and the underline goes here.
   On quotes.html and orders.html the strip also carries `data-tabs`: their
   Activity tab (and the list beside it) switch in place (owner, 2026-10-08).
   app.js switches only a `.tab[data-tab]`, so the links on the same strip
   still just navigate. */
.ord-hub .tab,
.ord-hub .tab:hover,
.ord-hub .tab:focus-visible { text-decoration: none; }
/* The count TRAILS the label on a hub tab ("Orders 14"), where app.css's
   `.tab .count` expects it to lead ("642 Slabs") and tightens the gap on its
   right. Same trick, other side: the count gives back the strip's own fluid
   gap and keeps a fixed 4px to the word it follows, so the figure reads as part
   of the label and not as a chip floating after it. */
.ord-hub .tab .count {
  margin-right: 0;
  margin-left: calc(4px - clamp(4px, 0.3vw + 2.2px, 8px));
}

/* ---------- The panel the strip attaches to ---------------------------------
   The brief's shell is `.tabs--attached` + `.tab-shell` + ONE `.card` holding
   the register. app.css merges a card into its shell only through a
   `[data-tab-panel]` wrapper — the in-page-tabs case — 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 same corrections app.css
   makes for a tabbed panel, said for a card that sits straight in the shell:
   the card gives up its chrome and keeps its header, body and dividers; its
   table drops the side inset because the shell's own 16px already stands it
   off (§20). Scoped to a shell that follows the hub strip, so no other panel
   on the platform is touched. */
.ord-hub ~ .tab-shell > .card { background: none; border: 0; border-radius: 0; box-shadow: none; }
.ord-hub ~ .tab-shell > .card > .card-header:first-child { padding-top: 0; }
.ord-hub ~ .tab-shell > .card:first-child > .card-body:first-child { padding-top: 0; }
.ord-hub ~ .tab-shell > .card > .table-wrap { padding-inline: 0; }
/* THE HEAD BAND COMES OFF ONLY WHILE THE TABLE IS THE FIRST THING IN THE PANEL.
   The shell's own lead-in is the platform's 10px (§18), so a band on top of it
   would pay the standoff twice. A bar that appears above the table — the bulk
   bar when rows are checked — is "something above the table" and the band has
   to come back under it the moment it shows; the second selector names a
   HIDDEN bar, because a bar that is in the DOM but not on screen is above
   nothing. The wrap's own top rule goes the same way: it separates a toolbar
   from a panel, and the bar is neither — the band is the whole separation. */
.ord-hub ~ .tab-shell > .card > .table-wrap:first-child .data-table thead th,
.ord-hub ~ .tab-shell > .card > [hidden] + .table-wrap .data-table thead th { border-top: 0; }
.ord-hub ~ .tab-shell > .card > .ord-bulk + .table-wrap { border-top: 0; }
/* The same sentence for the Activity tab's panel (quotes.html, orders.html):
   its applied-filter chips and custom date range open the panel above the log,
   and only while they show. Both hidden, the log is the first thing in the
   panel and gives up its head band and the wrap's top rule, as the list on
   the tab beside it does. */
.ord-hub ~ .tab-shell > [data-tab-panel] > .card > .activity-custom[hidden] + .activity-chips[hidden] + .table-wrap,
.ord-hub ~ .tab-shell > [data-tab-panel] > .card > .activity-custom[hidden] + .activity-chips[hidden] + .table-wrap .data-table thead th { border-top: 0; }

/* ---------- Register tables -------------------------------------------------
   Every Orders register is a `.data-table` whose columns take percentage
   shares of the table under `table-layout: fixed`, declared in the PAGE's own
   stylesheet because each register has its own columns. What they all 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 ("ORD-2026-0031 | E. Costa")
   is a mark between two facts rather than a character to be read, so it stands
   back from both and is drawn in the border colour, not the text one (the
   shape quotes.css gives `.req-table--all`). The check column centres its box
   and its row mark, because a 16px square at the left edge of a 48px column
   reads as an orphan. A status cell may carry a badge AND a hold word; the word
   always sits under the badge, a size down — beside it, the two read as one
   crowded line. */
.ord-table tbody tr { cursor: pointer; }
.ord-table .sub .sep { margin: 0 6px; color: var(--color-border-strong); }
.ord-table th.col-check,
.ord-table td.col-check { text-align: center; }
.ord-table tbody td.col-check::after { background: var(--row-mark-center); }
.ord-table td.col-status { white-space: normal; line-height: 1.9; }
.ord-table td.col-status .badge { vertical-align: middle; }
.ord-table td.col-status .ord-hold {
  display: flex; justify-content: flex-end; margin-top: 4px;
  font-size: 11px; line-height: 1.4;
}
.ord-table td.col-status .ord-hold svg { width: 12px; height: 12px; }
/* A plain reading under the badge (Paid 30%): the hold's size and place, in the
   subtle grey — a fact, not a warning. */
.ord-table td.col-status .ord-sub {
  display: block; margin-top: 4px;
  font-size: 11px; line-height: 1.4; color: var(--color-text-subtle);
}
/* The box itself: the primary as its accent, no margin of its own, and sized so
   it reads as a control and not as a stray square. */
.ord-check {
  width: 15px; height: 15px; margin: 0; vertical-align: middle;
  accent-color: var(--color-primary); cursor: pointer;
}

/* ---------- Readings: words, not chips --------------------------------------
   A side, a mode, a client type, an age, a count: each is a WORD in the row's
   own type, and several of them are one line joined by `·`. 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 are spent on the urgent reading alone:
   danger ink for the one already late or blocked, warn ink for the one due.

   The separator is drawn by CSS between children, so a reading with one child
   has none and no page ever types a stray dot. The reading is an inline-flex
   that wraps: children stand side by side while they fit and fall to the next
   line as whole readings when they do not, and a long child ("Designer for
   Henderson Residence") still wraps inside itself at a space. `.ord-progress`
   is the same shape with a name of its own, because a page may want its
   three stage readings addressed apart from the rest.

   THE DOT TRAILS THE WORD IT FOLLOWS, drawn as an `::after` on every child but
   the last — not as a `::before` on every child but the first. The two are the
   same row while the row fits; they differ the moment it wraps. A leading dot
   travels down with the child it belongs to and opens the second line with
   punctuation ("· Not invoiced"); a trailing dot stays at the end of the first
   line, where the eye expects a list to break. Register cells wrap at 1440. */
.ord-reading,
.ord-progress {
  display: inline-flex; flex-wrap: wrap; align-items: center;
  row-gap: 2px; max-width: 100%;
  font-size: 13px; color: var(--color-text);
}
.ord-reading > *,
.ord-progress > * { display: inline-flex; align-items: center; gap: 5px; }
.ord-reading > *:not(:last-child)::after,
.ord-progress > *:not(:last-child)::after {
  content: "·";
  margin: 0 6px 0 1px;
  color: var(--color-text-subtle);
  font-weight: 400;
}
/* An icon inside a reading is the size of the type beside it. */
.ord-reading svg,
.ord-progress svg { width: 14px; height: 14px; flex: none; color: var(--color-text-muted); }
.ord-reading .dot-status,
.ord-progress .dot-status { flex: none; }
.ord-reading .is-urgent { color: var(--color-danger-ink); font-weight: 600; }
.ord-reading .is-warn   { color: var(--color-warn-ink); }
/* The side word — "Supplier → Distributor", "Fabricator", "Homeowner via
   Meridian" — is a category, so it is grey (§19) and never a badge. */
.ord-side { color: var(--color-text-muted); }
/* The mode word with its lucide icon (ship · plane · truck · hand). A mode is
   one word and does not break: "Container 40 ft HC" split over two lines is
   two readings. */
.ord-mode { white-space: nowrap; }
.ord-mode svg { color: var(--color-text-muted); }
/* The three stage readings — Fulfilment · Paid · Invoiced — each a dot in the
   state's colour and a word. The dot is the mark, the word is the reading;
   a dot alone would fail the moment the screen is bad (§19). */
.ord-progress > * { white-space: nowrap; }
/* A hold flag as a word. Danger ink and weight, the shield beside it, and it
   never breaks: a hold is one fact. It stands beside a status badge in a
   register cell and beside the h1 on a detail page. */
.ord-hold {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12px; font-weight: 600; color: var(--color-danger-ink);
  white-space: nowrap; vertical-align: middle;
}
.ord-hold svg { width: 14px; height: 14px; flex: none; }
/* The Vava-network reading: a link icon and one of three phrases. Linked is a
   live state and takes the success ink; a request sent is a wait and takes
   warn; not on Vava is just a fact, in the muted grey. */
.ord-linked {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--color-text-muted); white-space: nowrap;
}
.ord-linked svg { width: 14px; height: 14px; flex: none; color: currentColor; }
.ord-linked.is-on      { color: var(--color-success-ink); }
.ord-linked.is-pending { color: var(--color-warn-ink); }

/* ---------- Container fill ---------------------------------------------------
   Stone fills a box by weight long before it fills it by volume, so a fill is
   never one bar: two rows, Weight and Volume, each a bar with its figures
   beside it, and one line naming which closes first. The label sits right-
   aligned against its bar and the figure follows the bar at once — nothing is
   spread to the row's far edge (memory.md §6, §16).

   THE BAR IS AN INLINE SVG, NOT `.stock-bar`. The house bar fills with an
   inline `style="width: 69%"`, and an inline style is forbidden here (§14) —
   a percentage has to travel in the markup some other way. An SVG `width`
   is a presentation attribute, not a style, so the level is a <rect> whose
   width IS the percentage:

     <div class="ord-fill">
       <span class="ord-fill__label">Weight</span>
       <svg class="ord-fill__bar" viewBox="0 0 100 6" preserveAspectRatio="none" aria-hidden="true">
         <rect class="ord-fill__level warn" width="99.9" height="6"></rect>
       </svg>
       <span class="ord-fill__fig">26,675 / 26,700 kg <span class="ord-fill__pct">99.9%</span></span>
       … the Volume row the same …
       <span class="ord-fill__closes"><strong>Weight closes first</strong> · 61% by volume</span>
     </div>

   The track takes the control ground (§13): an unfilled bar on a white card is
   not a bar. `.warn` and `.danger` on the level follow `.stock-bar`'s own
   names, and `--compact` is the same gauge sized for a table cell. */
.ord-fill {
  display: grid; grid-template-columns: max-content minmax(80px, 1fr) max-content;
  column-gap: 10px; row-gap: 6px; align-items: center;
  max-width: 440px;
  font-size: 12px; color: var(--color-text-muted);
}
.ord-fill__label { text-align: right; }
.ord-fill__bar {
  display: block; width: 100%; height: 6px;
  border-radius: 5px; overflow: hidden;
  background: var(--color-control);
}
.ord-fill__level { fill: var(--color-success); }
.ord-fill__level.warn   { fill: var(--color-warn); }
.ord-fill__level.danger { fill: var(--color-danger); }
.ord-fill__fig { color: var(--color-text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ord-fill__pct { font-weight: 600; margin-left: 4px; }
.ord-fill__closes { grid-column: 1 / -1; font-size: 11px; color: var(--color-text-muted); }
.ord-fill__closes strong { color: var(--color-warn-ink); font-weight: 600; }
.ord-fill--compact { max-width: 240px; column-gap: 8px; row-gap: 3px; font-size: 11px; }
.ord-fill--compact .ord-fill__bar { height: 5px; }
.ord-fill--compact .ord-fill__closes { font-size: 11px; }

/* ---------- The status path -------------------------------------------------
   A row of steps: done steps in success, the current one in warn and bold, the
   rest muted. Each step is a WORD with a mark before it — a dot in the state's
   colour and a hairline on to the next — so the path reads as the list of
   statuses the tenant configured (orders-workflow.html) and not as a progress
   bar. `--container` and `--local` change WHICH steps a page writes, never how
   one is drawn; `.is-exit` is for the side exits (Cancelled, Expired), drawn in
   danger when the record took one. */
.ord-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);
}
.ord-path__step { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.ord-path__step::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--color-border-strong);
}
.ord-path__step:not(:last-child)::after {
  content: ""; width: 18px; height: 1px; flex: none; margin: 0 8px 0 6px;
  background: var(--color-border-strong);
}
.ord-path__step.is-done { color: var(--color-success-ink); }
.ord-path__step.is-done::before,
.ord-path__step.is-done::after { background: var(--color-success); }
.ord-path__step.is-current { color: var(--color-warn-ink); font-weight: 600; }
.ord-path__step.is-current::before { background: var(--color-warn); box-shadow: 0 0 0 3px var(--color-warn-50); }
.ord-path__step.is-exit { color: var(--color-danger-ink); }
.ord-path__step.is-exit::before { background: var(--color-danger); }
/* `.ord-path--container` and `.ord-path--local` carry no rule of their own:
   which steps are present is the markup's business, and the drawing is one. */

/* ---------- Key–value grid ----------------------------------------------------
   Label right-aligned in the muted ink, value left-aligned, an 8px gap between
   — tight at the centre, never spread (memory feedback: label right, value
   left). Works on a <dl> (dt / dd) and on a div grid (__k / __v) alike. */
.ord-kv {
  display: grid; grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 8px; row-gap: 6px; align-items: baseline;
  margin: 0;
}
.ord-kv dt,
.ord-kv__k { margin: 0; text-align: right; font-size: 12px; color: var(--color-text-muted); white-space: nowrap; }
.ord-kv dd,
.ord-kv__v { margin: 0; min-width: 0; font-size: 13px; color: var(--color-text); }

/* ---------- The activity timeline ----------------------------------------------
   Time on the left in 11px muted type, a 6px dot, the event in 13px. One grid
   so the dots make a column whatever the width of the times; an <li> spreads
   its three cells into it with `display: contents`. */
.ord-timeline {
  display: grid; grid-template-columns: max-content 6px minmax(0, 1fr);
  column-gap: 10px; row-gap: 10px; align-items: baseline;
  margin: 0; padding: 0; list-style: none;
}
.ord-timeline > li { display: contents; }
.ord-timeline__time {
  font-size: 11px; color: var(--color-text-muted); text-align: right;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.ord-timeline__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-border-strong); align-self: center; }
.ord-timeline__dot.ok   { background: var(--color-success); }
.ord-timeline__dot.warn { background: var(--color-warn); }
.ord-timeline__dot.bad  { background: var(--color-danger); }
.ord-timeline__dot.new  { background: var(--color-info); }
.ord-timeline__text { min-width: 0; font-size: 13px; color: var(--color-text); }
.ord-timeline__text .who { font-size: 12px; color: var(--color-text-muted); }

/* ---------- A document row ------------------------------------------------------
   The PDF mark (img/ExportPDF.png at 24px), the document's name, its version
   as a word, a status badge and the actions. Rows divide with the border
   hairline; the last one closes on the card's own edge. */
.ord-doc {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 0; border-bottom: 1px solid var(--color-border);
  font-size: 13px;
}
.ord-doc:last-child { border-bottom: 0; }
.ord-doc__ico { width: 24px; height: 24px; flex: none; object-fit: contain; }
.ord-doc__name { font-weight: 500; color: var(--color-text); min-width: 0; }
.ord-doc__ver { font-size: 12px; color: var(--color-text-muted); white-space: nowrap; }
.ord-doc__acts { margin-left: auto; display: inline-flex; gap: 6px; flex: none; }

/* ---------- Photos ---------------------------------------------------------------
   72px thumbnails from img/products/, in a grid that packs as many as fit. A
   trailing "+28" cell for the ones not drawn stands on the control ground. */
.ord-photos { display: grid; grid-template-columns: repeat(auto-fill, 72px); gap: 8px; }
.ord-photos img,
.ord-photos__more {
  width: 72px; height: 72px; display: block; object-fit: cover;
  border-radius: var(--radius); border: 1px solid var(--color-border);
}
.ord-photos__more {
  display: flex; align-items: center; justify-content: center;
  background: var(--color-control); border-color: var(--color-control-border);
  color: var(--color-text-muted); font-size: 12px; font-weight: 500;
}

/* ---------- 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. The bar stands on the
   control ground because it is a thing inside a white panel (§13). `[hidden]`
   has to be restated: the bar sets its own `display`, which would otherwise
   beat the browser's hidden rule and leave the bar showing with nothing
   checked. */
.ord-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);
}
.ord-bulk[hidden] { display: none; }
.ord-bulk__count { font-size: 13px; color: var(--color-text-muted); white-space: nowrap; margin-right: 6px; }
.ord-bulk__count strong { color: var(--color-text); font-weight: 600; font-variant-numeric: tabular-nums; }
.ord-bulk__clear { margin-left: auto; }

/* ---------- A two-sided choice ----------------------------------------------------
   "Save for: Me | Miami Yard", "Total | Hide": a yes/no is a switch with BOTH
   sides labelled, and the side in force is told by colour and weight — never
   an underline, never a label that moves, and nothing boxed behind it. The one
   place the switch does not lead its label (§5), because here it stands
   between its two answers. Shape copied from quotes.css `.req-sums`. */
.ord-sides { display: inline-flex; align-items: center; gap: 10px; }
.ord-sides__lead { font-size: 12px; color: var(--color-text-muted); margin-right: 2px; }
.ord-sides__opt {
  font-size: 12px; font-weight: 500; color: var(--color-text-muted);
  white-space: nowrap; cursor: pointer;
  transition: color 120ms;
}
.ord-sides__opt.is-active { color: var(--color-text); font-weight: 600; }

/* ---------- Page-gear dialogs -------------------------------------------------------
   Manage KPIs, Manage Columns and Saved Views open from the gear on every
   register, so their pieces are shared.

   MANAGE KPIS adds one answer to the house reorder row: how wide the tile
   draws (¼ ⅓ ½). The select is sized to its three glyphs (§9) and stands
   straight after the label it answers rather than at the row's far edge
   (§16) — app.css stretches the label to fill the row, so the stretch is
   undone here and the slack falls after the select instead. */
.ord-kpi-row .switch-field { flex: none; }
.ord-kpi-width {
  width: auto; flex: none;
  padding: 4px 26px 4px 9px; font-size: 12px;
  background-position: right 8px center;
}
/* MANAGE COLUMNS: the first column is the record and cannot be hidden, so its
   row is locked — the grip fades and the switch is stated, not offered. */
.ord-cols .reorder-item.is-locked .reorder-grip { opacity: .35; cursor: default; }
.ord-cols .reorder-item.is-locked .switch { opacity: .55; pointer-events: none; }
.ord-col-note { font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.ord-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. */
.ord-dialog-note { margin: 10px 0 0; font-size: 12px; color: var(--color-text-subtle); }
/* SAVED VIEWS: each view is a row on the control ground (a box inside a white
   dialog, §13) — the mark, the name with what it narrows to, who it is saved
   for, and Apply. */
.ord-views { display: flex; flex-direction: column; gap: 6px; }
.ord-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);
}
.ord-view .cell-stack { flex: 1; min-width: 0; }
.ord-view__ico { width: 16px; height: 16px; flex: none; color: var(--color-text-subtle); }
.ord-view__who { font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.ord-view-save { margin-top: 16px; }
.ord-view-save__row { align-items: stretch; }
.ord-view-save__row .btn { flex: none; }

/* ---------- Empty state ---------------------------------------------------------------
   "No claims on this order": a sentence on the control ground with the one
   action that would change it. */
.ord-empty {
  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);
}
.ord-empty .btn { margin-top: 10px; }

/* ---------- The container chart ---------------------------------------------------------
   The same live OpenStreetMap embed as the showroom workspace's Where It Is
   Now drawer (.ps-map, css/showroom.css). The frame is 40px shorter than the
   iframe so OSM's own credit bar crops out; the credit is re-stated beside
   the map (.ord-map__credit). The wrapper gives the border. */
.ord-map { height: 280px; overflow: hidden; background: #E8E4DC; }
.ord-map iframe { display: block; width: 100%; height: 320px; border: 0; }
.ord-map__credit { margin: 6px 0 0; font-size: 10px; color: var(--color-text-subtle); }
@media (max-width: 768px) {
  .ord-map { height: 220px; }
  .ord-map iframe { height: 260px; }
}

/* ---------- Narrow screens ------------------------------------------------------------
   Touch targets grow to the 44px floor; the key–value grid stacks its label
   over its value because a right-aligned label column on a 390px screen
   leaves the value a few words wide. */
@media (max-width: 768px) {
  .ord-bulk .btn,
  .ord-doc__acts .btn { min-height: 44px; }
  .ord-kv { grid-template-columns: 1fr; row-gap: 2px; }
  .ord-kv dt,
  .ord-kv__k { text-align: left; }
  .ord-kv dd + dt,
  .ord-kv__v + .ord-kv__k { margin-top: 8px; }
  .ord-fill { max-width: none; }
}
@media (max-width: 480px) {
  .ord-bulk { gap: 6px; }
  .ord-bulk__count { flex-basis: 100%; margin-right: 0; }
  .ord-bulk__clear { margin-left: 0; }
  .ord-view { flex-wrap: wrap; }
  .ord-view__who { flex-basis: 100%; padding-left: 26px; }
}

/* ---------- An order's products (js/order-lines.js) ---------------------------------
   quote.html's Products tab carried on to the order: quotes.css draws the
   groups, the rows, the typing row and the state badge. What an order adds is
   one column, the Shipment, between the material and its price, and the exact
   units each material opens to. It drops the quote's date column (owner,
   2026-10-09): every line came over from the quote together, so the day each
   was first asked for says nothing on the order. */
.req-mats--dated.req-mats--order .req-mat,
.req-mats--dated.req-mats--order .req-entry-row,
.ord-unit {
  grid-template-columns: minmax(0, 1fr) 120px 132px 128px 108px 104px;
}
.req-mats--dated.req-mats--order .req-entry-row .req-mat-menu { grid-column: 6; gap: 2px; }
.ord-mat-ship { min-width: 0; font-size: 12px; }
/* The quantity's sub carries the weight too; it wraps rather than run into
   the price beside it. */
.req-mats--dated.req-mats--order .req-mat-qty-sub { white-space: normal; text-align: right; }
.ord-mat-ship .cell-stack .main { font-size: 12px; font-weight: 500; }
.ord-mat-ship a { color: var(--color-primary-600); text-decoration: none; }
.ord-mat-ship a:hover { color: var(--color-primary-700); }
/* The badge's dialog opens beside it (quote.html sets this inline). */
.req-mats--dated.req-mats--order .req-step { position: relative; }
/* A Picked or Loaded line is locked: its badge reads but opens nothing. */
.req-mat-status.ord-mat-status--flat { cursor: default; }
.req-mat-status.ord-mat-status--flat:hover { border-color: transparent; }

/* One row per material or one per product (owner, 2026-10-09): a group /
   ungroup icon pair, leading the strip's trailing controls, left of + Stone
   Type, at the small buttons' height. */
.req-lines-view { margin-left: auto; align-self: center; flex: none; height: 30px; }
.req-lines-view + .req-add-stone,
.req-lines-view ~ .rowfilter { margin-left: 10px; }
html[data-licence="distributor"] .bp-sides:not([hidden]) + .req-lines-view { margin-left: 14px; }

/* The units under the name: the mix in words, and the press opens them. No
   underline on the press (memory): colour carries it. */
.ord-units-tog {
  display: inline-flex; align-items: center; gap: 2px; align-self: flex-start;
  margin-top: 2px; padding: 0; border: 0; background: none;
  font: inherit; font-size: 11px; color: var(--color-text-muted); cursor: pointer;
}
.ord-units-tog svg { width: 12px; height: 12px; margin-left: -2px; transition: transform 120ms ease; }
.ord-units-tog[aria-expanded="true"] svg { transform: rotate(90deg); }
.ord-units-tog:hover { color: var(--color-primary-700); }
.ord-units-none { margin-top: 2px; font-size: 11px; color: var(--color-text-subtle); }

/* Open, the units run under the row on its own columns: blocks, then
   bundles, then slabs, then the rest; a bundle opens to its slab sizes. */
.ord-units { grid-column: 1 / -1; margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--color-border); }
.ord-unit { display: grid; align-items: center; gap: 12px; padding: 5px 0; }
/* Indented to the material's name, so a unit reads as under it now that no
   date column sets the rows apart. */
.ord-unit-body { display: flex; align-items: center; gap: 8px; min-width: 0; padding-left: 22px; }
.ord-unit .cell-stack .main { font-size: 12px; font-weight: 500; }
.ord-unit .cell-stack .sub { font-size: 11px; }
.ord-unit .req-mat-price { font-size: 12px; }
.ord-unit .req-mat-total.ord-unit-total { font-size: 12px; font-weight: 400; }
.ord-unit-loc { font-size: 12px; color: var(--color-text-muted); }
.ord-unit--size .ord-unit-body { padding-left: 52px; }
.ord-kind { flex: none; width: 16px; height: 16px; color: var(--color-text-muted); stroke-width: 1.5; }
.ord-tog {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0; border: 0; border-radius: var(--radius);
  background: none; color: var(--color-text-muted); cursor: pointer;
}
.ord-tog:hover { background: var(--color-control); color: var(--color-text); }
.ord-tog svg { width: 14px; height: 14px; transition: transform 120ms ease; }
.ord-tog[aria-expanded="true"] svg { transform: rotate(90deg); }
.ord-tog-gap { flex: none; width: 22px; }

@media (max-width: 760px) {
  /* The row stacks as quote.html's does, with the shipment under the name. */
  .req-mats--dated.req-mats--order .req-mat {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "body  body"
      "ship  ship"
      "price qty"
      "total state";
  }
  .req-mats--dated.req-mats--order .req-entry-row {
    grid-template-columns: minmax(0, 1fr) 84px 72px;
    grid-template-areas:
      "body  body  menu"
      "ship  ship  ship"
      "price qty   qty"
      "total total total";
  }
  .req-mats--dated.req-mats--order .req-entry-row .req-mat-menu { grid-column: auto; grid-area: menu; }
  .ord-mat-ship { grid-area: ship; }
  .ord-units { grid-area: auto; grid-column: 1 / -1; }
  .ord-unit {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "body body"
      "loc  qty"
      ".    total";
    row-gap: 2px;
  }
  .ord-unit > span:last-child, .ord-unit .req-mat-price { display: none; }
  .ord-unit-body { grid-area: body; padding-left: 0; }
  .ord-unit--size .ord-unit-body { padding-left: 30px; }
  .ord-unit-loc { grid-area: loc; }
  .ord-unit .req-mat-qty { grid-area: qty; }
  .ord-unit .req-mat-total { grid-area: total; text-align: right; }
  .ord-units-tog { min-height: 32px; }
  /* The stone's head wraps: its subtotal drops under the name rather than
     run off the screen (quote.html's head has the same overflow). */
  [data-ord-lines] .req-area-head { flex-wrap: wrap; row-gap: 4px; }
  [data-ord-lines] .req-area-sub { margin-left: 0; flex-basis: 100%; }
}
