/* ==========================================================================
   Orders — the order detail (order.html)

   Spec: build/pages.md §3

   Only what is this page's own: the detail header (quote.html's shape, said
   with this page's `odt-` names because the quote's classes live in
   quotes.css and an Orders page links orders.css), the figure bar, the lines
   table's column shares and material group rows, the shipment block, the
   payment and invoice tables, the dialog rows, and how it all folds at
   1200 / 1100 / 768 / 480. Everything another Orders page also says — the
   readings, the hold word, the path, the fill gauge, the key–value grid, the
   timeline, the document row, the two-sided choice — is orders.css's.

   Tokens only, light theme only; radius never passes 7px; nothing under 10px.
   ========================================================================== */

/* ---------- Detail header ---------------------------------------------------
   A grid, so the page actions share the TITLE line only: the chip row under it
   runs the full width beneath the buttons instead of wrapping beside them. The
   left block dissolves (`display: contents`) so its three lines are cells. */
.odt-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 16px; align-items: center; }
.odt-head > :first-child { display: contents; }
.odt-crumb { grid-column: 1 / -1; grid-row: 1; }
.odt-title-row { grid-column: 1; grid-row: 2; min-width: 0; }
.odt-head .page-actions { grid-column: 2; grid-row: 2; }
.odt-badges { grid-column: 1 / -1; grid-row: 3; }
.odt-crumb {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 4px; font-size: 12px; color: var(--color-text-subtle);
}
.odt-crumb a { color: var(--color-text-muted); text-decoration: none; }
.odt-crumb a:hover { color: var(--color-primary-700); }
/* The number and the status are one line, centred on each other. */
.odt-title-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.odt-head .page-title { display: inline-flex; align-items: baseline; flex-wrap: wrap; }
/* The trail reads Orders / the client; the slash is joinery, so it is muted. */
.odt-crumb-sep { color: var(--color-text-subtle); }
/* The status stands against 22px type, so it is scaled to stand as tall as the
   number while its word stays a clear step under the heading. Colour comes
   from the badge family (memory.md §19), nothing of its own. */
.odt-status { font-size: 14px; padding: 5px 12px; }
.odt-status .dot { width: 7px; height: 7px; }
/* The status is a button that opens its moves (app.css .req-step-pop), as on
   orders.html; a hover border is the only tell. In the header the card drops
   below the badge instead of standing to its left. */
.odt-step { position: relative; display: inline-block; }
.odt-step-btn { cursor: pointer; line-height: inherit; }
.odt-step-btn:hover { border-color: currentColor; }
.odt-step .dropdown-menu.req-step-pop { top: calc(100% + 8px); left: 0; right: auto; transform: none; }
/* The row of things that can be SET, and the rep who owns the order. */
.odt-badges { display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap; margin-top: 6px; }
.odt-badges .subtle { font-size: 12px; }
.odt-badges .ord-reading { font-size: 12px; }
.odt-hold-end { margin-left: auto; }
/* A settable field reads as text until you reach for it; the pencil is always
   there, in the lightest ink. */
.odt-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: 2px 6px; margin-left: -6px;
  font: inherit; font-size: 12px; color: inherit; text-decoration: none;
}
.odt-field:hover { border-color: var(--color-border); background: var(--color-surface); color: inherit; }
.odt-field svg { width: 12px; height: 12px; flex: none; color: var(--color-text-subtle); }
.odt-field .odt-edit { opacity: 1; }
.odt-field--static { cursor: pointer; }
.odt-field--static span { font-weight: 500; }
/* An icon button in the action row keeps the row's height (quotes.css). */
.odt-head .page-actions .icon-btn { height: auto; }

/* ---------- The figure bar ---------------------------------------------------
   One box, a hairline between readings, the number leading on a line of its
   own and the word under it (quotes.css `.req-stats--bar --stack`). The gap
   under it is the 25px every box above an attached strip takes. */
.odt-stats {
  display: flex; flex-wrap: wrap; align-items: stretch; gap: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  margin-bottom: 25px;
  overflow: hidden;
}
.odt-stat {
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 1px;
  padding: 8px 14px;
  /* The hairline between readings is a shadow, not a border, so it clips on the
     bar's own edge wherever the row folds. */
  box-shadow: -1px 0 0 0 var(--color-border);
}
.odt-stat .v { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; color: var(--color-text); font-variant-numeric: tabular-nums; line-height: 1.2; }
.odt-stat .l { font-size: 12px; color: var(--color-text-muted); white-space: nowrap; }
.odt-stat .s { font-size: 11px; color: var(--color-text-subtle); white-space: nowrap; }
.odt-stat--ok .v { color: var(--color-success-ink); }
.odt-stat--due .v { color: var(--color-danger-ink); }
.odt-stat-line { display: inline-flex; align-items: baseline; gap: 6px; }
/* The fill gauge closes the bar and takes the slack: two bars with their
   figures beside them, and the word that says which closes first. */
.odt-stat--fill { flex: 1 1 260px; min-width: 0; padding-top: 7px; padding-bottom: 7px; }
.odt-stat--fill .ord-fill { max-width: none; width: 100%; }

/* ---------- Panel heads -------------------------------------------------------
   Every tab is one card merged into the shell. Its header carries the name,
   a reading under it, and the actions on the right as one group that wraps. */
.odt-card-head { gap: 12px; flex-wrap: wrap; }
.odt-card-head > div:first-child { min-width: 0; }
.odt-card-head .sub .ord-reading { font-size: 12px; color: var(--color-text-subtle); }
.odt-card-head .sub .ord-reading strong { color: var(--color-text); font-weight: 600; }
.odt-card-acts { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
/* A locked action: it looks disabled but still answers a tap with why, which a
   disabled button's hover title cannot do on a touch screen. */
.btn.odt-locked { opacity: 0.45; cursor: not-allowed; }
/* A line of explanation under a panel's content, in the hint type. */
.odt-note { margin: 12px 0 0; font-size: 12px; color: var(--color-text-subtle); }
.odt-empty-sub { display: block; margin-top: 4px; font-size: 12px; color: var(--color-text-subtle); }
/* Products sits outside the shell as quote.html's does (its stones are cards
   of their own), so the empty shell goes while that tab is open. */
.tab-shell:not(:has(> [data-tab-panel]:not([hidden]))) { display: none; }

/* ---------- Details side panel ---------------------------------------------------
   Shipments, Payments, Invoices, Documents and Claims as vertical tabs in one
   wide side panel. The nav stays put; only the pane scrolls. The pane stands
   on the page ground so the cards inside it read as cards (memory.md §13). */
#modal-details .slideover { width: min(1200px, 100%); }
.odt-details__body { display: grid; grid-template-columns: 168px minmax(0, 1fr); padding: 0; overflow: hidden; }
.odt-details__nav { display: flex; flex-direction: column; gap: 2px; padding: 12px 8px; border-right: 1px solid var(--color-border); }
.odt-details__nav .subtab { justify-content: flex-start; width: 100%; border-radius: var(--radius); }
.odt-details__nav .subtab svg { width: 15px; height: 15px; flex: none; }
.odt-details__nav .subtab .count { margin-left: auto; }
.odt-details__pane { min-width: 0; overflow-y: auto; padding: 16px; background: var(--color-bg); }
@media (max-width: 768px) {
  .odt-details__body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  .odt-details__nav { flex-direction: row; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--color-border); }
  .odt-details__nav .subtab { width: auto; flex: none; }
}

/* ---------- Shipments -----------------------------------------------------------
   One block per shipment on the control ground (a box inside the white
   panel, memory.md §13): its head line, two columns of facts, and the
   documents gate as its foot. */
.odt-ship {
  background: var(--color-control);
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius);
  padding: 14px 16px;
}
.odt-ship + .odt-ship { margin-top: 12px; }
.odt-ship__head { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; margin-bottom: 14px; }
.odt-ship__title { font-size: 14px; font-weight: 600; }
.odt-ship__title a { color: var(--color-text); text-decoration: none; }
.odt-ship__title a:hover { color: var(--color-primary-700); }
.odt-ship__acts { margin-left: auto; display: inline-flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.odt-ship__grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 16px 32px; }
.odt-ship__col { min-width: 0; }
.odt-ship__col h4 {
  margin: 0 0 8px; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--color-text-muted);
}
.odt-ship__h4-gap { margin-top: 16px !important; }
.odt-ship .ord-fill { max-width: none; }
/* The gauge's track sits on the control ground here, so it takes the white. */
.odt-ship .ord-fill__bar { background: var(--color-surface); }
.odt-ship .ord-kv dd .ord-hold { font-size: 12px; }
.odt-ship__foot {
  display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--color-control-border);
  font-size: 12px; color: var(--color-text-muted);
}
.odt-ship__foot .ord-reading { font-size: 12px; }
/* Thumbnails on the control ground take a white edge; the "+37" cell inverts. */
.odt-ship .ord-photos img { border-color: var(--color-surface); }
.odt-ship .ord-photos__more { background: var(--color-surface); border-color: var(--color-border-strong); cursor: pointer; font: inherit; font-size: 12px; font-weight: 500; }

/* ---------- Payments and invoices --------------------------------------------------- */
.odt-pay th.col-date    { width: 15%; }
.odt-pay th.col-method  { width: 20%; }
.odt-pay th.col-ref     { width: 14%; }
.odt-pay th.col-applied { width: 19%; }
.odt-pay th.col-status  { width: 15%; }
.odt-pay th.col-amount  { width: 17%; }
.odt-inv th.col-number  { width: 20%; }
.odt-inv th.col-type    { width: 21%; }
.odt-inv th.col-issued  { width: 15%; }
.odt-inv th.col-status  { width: 17%; }
.odt-inv th.col-due     { width: 12%; }
.odt-inv th.col-amount  { width: 15%; }
.odt-inv tbody tr { cursor: pointer; }
.odt-pay td a, .odt-inv td a { color: var(--color-primary-600); text-decoration: none; }
.odt-pay td a:hover, .odt-inv td a:hover { color: var(--color-primary-700); }
.odt-inv td.col-status { white-space: normal; line-height: 1.9; }
.odt-inv td.col-status .badge { vertical-align: middle; }
/* Where the invoices are made: the tenant's invoicing source (Orders Settings),
   read as words above the rows; each row says it came back from that source. */
.odt-sync { display: flex; align-items: center; gap: 5px; font-size: 11px; line-height: 1.4; color: var(--color-text-subtle); }
/* The summary under the ledger: two key–value grids side by side, each
   reading label right, value left, tight (memory feedback). */
.odt-pay-summary { border-top: 1px solid var(--color-border); }
.odt-kv-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 32px; }
.odt-kv-2 .ord-kv dd strong { font-weight: 600; }
.card-footer a { color: var(--color-primary-600); text-decoration: none; }
.card-footer a:hover { color: var(--color-primary-700); }

/* ---------- Documents ------------------------------------------------------------------
   Under each document row, its send log in the hint type, on a line of its
   own and indented past the PDF mark. */
.odt-doc-log { flex-basis: 100%; padding-left: 34px; font-size: 11px; color: var(--color-text-subtle); }
.ord-doc .ord-doc__acts .btn-sm svg { width: 14px; height: 14px; }

/* ---------- Activity -------------------------------------------------------------------- */
.odt-act[hidden] { display: none; }
.odt-card-acts .subtabs { margin-bottom: 0; }

/* ---------- Dialogs -----------------------------------------------------------------------
   Field widths are sized to their content (memory.md §9): a date or a
   percentage is narrow, a name or an address wide. */
.odt-f-narrow { flex: 0 1 120px; }
.odt-f-mid    { flex: 1 1 180px; }
.odt-f-wide   { flex: 2 1 260px; }
.odt-f-half   { flex: 1 1 240px; }
/* A date alone on its row (Mark Arrived): held at the date's width. */
.form-row > .odt-f-date { flex: 0 0 140px; }
/* In a slide-over there is room to spare, so a field is fixed at what its
   longest value needs (plus headroom for other languages) and never grows. */
:is(.field, .select).odt-fit-dep    { flex: none; width: 96px; }
:is(.field, .select).odt-fit-method { flex: none; width: 160px; max-width: 100%; }
:is(.field, .select).odt-fit-mode   { flex: none; width: 230px; max-width: 100%; }
:is(.field, .select).odt-fit-dest   { flex: none; width: 250px; max-width: 100%; }
:is(.field, .select).odt-fit-due    { flex: none; width: 300px; max-width: 100%; }
.modal-body .form-row,
.slideover-form .slideover-body .form-row,
.odt-edit .form-row { flex-wrap: wrap; }
/* Edit Order is a tab of Details now, in a card: the slide-over form's own
   field rhythm (app.css, `.slideover-form`), carried with it. */
.odt-edit :is(.field, .field-grid, .form-row) + :is(.field, .field-grid, .form-row) { margin-top: 14px; }
.odt-edit .form-row > .field + .field,
.odt-edit .field-grid > .field { margin-top: 0; }
.odt-edit .card-footer { justify-content: flex-end; }
.odt-edit .alert { margin-bottom: 16px; }
.odt-hint { font-size: 11px; color: var(--color-text-subtle); }
.odt-hint .ord-reading, .odt-hint .ord-linked { font-size: 11px; }
.odt-dialog-h { margin: 18px 0 8px; font-size: 13px; font-weight: 600; }
.odt-gap-top { margin-top: 14px; }
.odt-foot-note { font-size: 11px; color: var(--color-text-subtle); align-self: center; }
.odt-self-start { align-self: flex-start; }
/* A percentage input with its unit at the end, in the input's own box. */
.odt-dep { position: relative; }
.odt-dep .input { padding-right: 26px; }
.odt-dep__unit { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); font-size: 12px; color: var(--color-text-muted); pointer-events: none; }
/* A box inside a dialog (the shipment, the bank details) sits on the control ground. */
.odt-well { background: var(--color-control); border: 1px solid var(--color-control-border); border-radius: var(--radius); padding: 12px 14px; }
.odt-well__head { display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap; margin-bottom: 12px; font-size: 13px; }
.odt-well .ord-dialog-note { margin-top: 10px; }
.odt-well .form-row { margin-top: 0; }
/* A two-sided choice on its own row, with its note under it. */
.odt-sides-row { margin-top: 16px; }
.odt-sides-row .ord-dialog-note { margin-top: 6px; }
/* A pickable line in Split and Claim: a row on the control ground, the box
   leading and the line's two facts after it. */
.odt-pick {
  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);
}
.odt-pick + .odt-pick { margin-top: 6px; }
.odt-pick .cell-stack { flex: 1; min-width: 0; cursor: pointer; }
.odt-pick.is-off { opacity: .6; }
.odt-pick.is-off .cell-stack { cursor: default; }
.modal-body .switch-field { font-size: 13px; color: var(--color-text); }

/* ---------- Narrow screens ----------------------------------------------------------------- */
@media (max-width: 1200px) {
  .odt-ship__grid { grid-template-columns: 1fr; }
}
@media (max-width: 1100px) {
  /* Below 1100 the title block and the action row no longer share a line: the
     block takes the full width and the actions drop under it, instead of the
     heading being squeezed to a column of single words beside four buttons. */
  .odt-head { grid-template-columns: minmax(0, 1fr); }
  .odt-head .page-actions { grid-column: 1; grid-row: 4; margin-top: 10px; }
}
@media (max-width: 1100px) {
  /* Nine columns fight below 1100: the table keeps its shares on a 960px
     table and scrolls inside .table-wrap (the house pattern). */
  .odt-pay, .odt-inv { min-width: 760px; }
}
@media (max-width: 768px) {
  .odt-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .odt-stat { box-shadow: -1px -1px 0 0 var(--color-border); }
  .odt-stat--fill { grid-column: 1 / -1; }
  .odt-kv-2 { grid-template-columns: 1fr; }
  .odt-card-head { flex-direction: column; align-items: stretch; }
  .odt-card-acts { justify-content: flex-start; }
  .odt-card-acts .btn { min-height: 44px; }
  .odt-ship__acts { margin-left: 0; flex-basis: 100%; }
  .odt-field { min-height: 32px; }
}
@media (max-width: 480px) {
  .odt-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .odt-stat .l, .odt-stat .s { white-space: normal; }
  .odt-head .page-title { font-size: 19px; }
  .page-actions { flex-wrap: wrap; }
  .odt-doc-log { padding-left: 0; }
  .odt-ship { padding: 12px; }
  .odt-f-narrow, .odt-f-mid, .odt-f-wide, .odt-f-half { flex-basis: 100%; }
  /* The footer's pager runs past a phone's edge when held to one line; let it
     wrap instead. */
  .tab-shell .card-footer { flex-wrap: wrap; gap: 8px; }
  .tab-shell .card-footer .page-controls { margin-left: 0; flex-wrap: wrap; row-gap: 6px; }
  .tab-shell .card-footer .pager { flex-wrap: wrap; }
}
