/* tables */
.table-wrap { overflow-x: auto; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-card); box-shadow: var(--shadow); }
.table-wrap table { margin: 0; }
/* Twin top scrollbar: a thin overflow-x strip built above a wide .table-wrap by
   initTableScrollSync so the horizontal scrollbar is reachable without scrolling to
   the bottom. Its spacer is widened (via CSSOM) to the table content width → a real
   native scrollbar; scrollLeft mirrors the table both ways. Hidden (.is-on toggled in
   JS) until the table actually overflows; the native bottom scrollbar above stays. */
.table-scroll-top { display: none; overflow-x: auto; overflow-y: hidden; margin-bottom: 2px; }
.table-scroll-top.is-on { display: block; }
.table-scroll-spacer { height: 1px; }
@media print { .table-scroll-top { display: none !important; } }
table { width: 100%; border-collapse: collapse; }
th { text-align: left; font-size: var(--fs-12); text-transform: uppercase; letter-spacing: .03em; color: var(--muted); padding: 5px 13px; border-bottom: 2px solid var(--line); background: var(--panel); }
/* Standard data-table alignment. CELLS: text columns read left, numbers right
   (tabular figures), dates and pure-% centered. HEADERS: every column title is centred
   (rule just below), whatever its cell alignment. The default here is wrapped in
   :where() (specificity 0,0,1 — element only) so the nature class ui.table puts on BOTH
   th and td wins on its own: .num-col → right (line 141), .date-col / .center-col →
   center, plus the manual .num / .right utilities of hand-written rows. Scoped to real
   column grids (.table-wrap, table.mini); the label→value blocks table.kv /
   table.totals keep their own base alignment. .td-actions (right) and .bulk-cell
   (center) keep their single-class win on the cells. */
:where(.table-wrap, table.mini) th, :where(.table-wrap, table.mini) td { text-align: left; }
/* Column titles are always centred — beats every nature class on the header (0,1,1 >
   0,1,0), so a new column centres its header with zero per-call work while its cells
   keep the nature alignment above. Scoped like the default; table.kv row-labels (left)
   are untouched. */
.table-wrap th, table.mini th { text-align: center; }
td { padding: 4px 13px; border-bottom: 1px solid var(--line); line-height: 1.35; }
/* One row = one line: cells never wrap, so a long value rides a horizontal scrollbar
   (.table-wrap is overflow-x:auto) instead of breaking onto a 2nd line. Full-width
   rows {full} (a document comment / sub-total band) keep wrapping; .cell-wrap is a
   per-cell opt-out. */
.table-wrap th, .table-wrap td { white-space: nowrap; }
.table-wrap td[colspan], .table-wrap .cell-wrap { white-space: normal; }
/* Pure-text column (a designation): cap its width and ellipsize an over-long value so
   one cell can't widen the whole table; the inline-block max-width also bounds the
   auto-layout column. Full text on a title tooltip (set by ui.table). */
.cell-ellip { display: inline-block; max-width: var(--col-text-max); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.table-wrap tbody tr:last-child td { border-bottom: 0; }
.card .table-wrap { border: 0; box-shadow: none; border-radius: 0; background: transparent; }
tbody tr { transition: background .12s; }
tbody tr:hover { background: var(--row-hover); }
tbody tr[data-href] { cursor: pointer; }
/* Sortable headers (ui.table → app.js [data-sort]): discreet hover affordance +
   a direction arrow on the active column. The neutral ↕ hint shows only on
   hover/focus so resting headers stay clean; the active column keeps a solid
   ▲/▼. The reserved indicator width avoids any layout shift between states. */
th.th-sort { cursor: pointer; user-select: none; white-space: nowrap; transition: background .12s, color .12s; }
th.th-sort:hover, th.th-sort:focus-visible { background: var(--chip); color: var(--ink-2); }
th.th-sort:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.sort-ind { display: inline-block; width: 1em; margin-left: 2px; font-size: var(--fs-10); text-align: center; vertical-align: middle; }
/* Phantom mirror of .sort-ind on the left: every header is centred now, so the
   (label + trailing indicator) block centres and shifts the visible label left by half
   the arrow's footprint. An equal-footprint spacer on the left re-centres the label
   itself — applied to every sortable header. */
th.th-sort::before { content: ''; display: inline-block; width: 1em; margin-right: 2px; font-size: var(--fs-10); vertical-align: middle; }
.sort-ind::after { content: '↕'; opacity: 0; transition: opacity .12s; }
th.th-sort:hover .sort-ind::after, th.th-sort:focus-visible .sort-ind::after { opacity: .4; }
th[aria-sort="ascending"] .sort-ind::after { content: '▲'; opacity: 1; }
th[aria-sort="descending"] .sort-ind::after { content: '▼'; opacity: 1; }
table.mini td, table.mini th { padding: 6px 8px; font-size: var(--fs-13); }
table.mini { border: 0; }

/* Bulk selection (ui.bulkList → app.js [data-bulk]): a mailbox-style list whose
   rows can be checkbox-selected to run a grouped action. The « Sélectionner » toggle
   rides the filter row; the checkbox column and the tools strip are dormant until
   it adds .bulk-on, so the inactive list costs no extra line. */
.bulk-tools { display: none; align-items: center; gap: 10px; flex-wrap: wrap; }
.bulk.bulk-on .bulk-tools { display: flex; margin-bottom: 12px; }
.bulk-count { font-size: var(--fs-13); color: var(--muted); min-width: 8ch; }
.bulk-picks { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { padding: 4px 11px; border: 1px solid var(--line); border-radius: 999px; background: var(--panel);
  color: var(--ink-2); font: inherit; font-size: var(--fs-13); cursor: pointer; transition: background .12s, color .12s; }
.chip:hover { background: var(--chip); color: var(--ink); }
.bulk-cell { display: none; width: 1px; white-space: nowrap; text-align: center; }
.bulk.bulk-on .bulk-cell { display: table-cell; }
.bulk.bulk-on tbody tr:has(.bulk-cb:checked) { background: var(--brand-wash); }
.bulk.bulk-on tbody tr[data-href] { cursor: pointer; }
table.kv th { width: 160px; text-transform: none; font-size: var(--fs-13); color: var(--muted); border: 0; font-weight: var(--fw-medium); vertical-align: top; }
table.kv td { border: 0; }
table.totals { width: auto; margin-left: auto; margin-top: 14px; min-width: 280px; }
table.totals th, table.totals td { padding: 3px 14px; }
table.totals th { text-transform: none; border: 0; color: var(--ink); font-weight: var(--fw-medium); }
table.totals td { border: 0; text-align: right; font-variant-numeric: tabular-nums; }
table.totals tr.grand th, table.totals tr.grand td { font-size: var(--fs-17); font-weight: var(--fw-bold); border-top: 2px solid var(--line); padding-top: 8px; }
/* A grand row that is the whole total (no preceding line, e.g. an order's « Total
   HT ») has nothing to separate from — drop its top border/padding. */
table.totals tr.grand:first-child th, table.totals tr.grand:first-child td { border-top: 0; padding-top: 3px; }
/* Internal margin row: dashed separator marks it as a display-only artifact, never on the PDF. */
table.totals tr.margin-row th, table.totals tr.margin-row td { border-top: 1px dashed var(--line); padding-top: 8px; }
table.totals tr.margin-row th { color: var(--muted); }
/* Subtotals-by-group recap (Pièces / Main d'œuvre / Frais) above the totals
   (PLAN_NATURES_ARTICLES lot 3): muted, lighter rows; the first non-subtotal row
   below them carries the separator that closes the recap. */
table.totals tr.subtotal-row th, table.totals tr.subtotal-row td { color: var(--muted); font-weight: var(--fw-normal); padding-top: 2px; padding-bottom: 2px; }
table.totals tr.subtotal-row + tr:not(.subtotal-row) th, table.totals tr.subtotal-row + tr:not(.subtotal-row) td { border-top: 1px solid var(--line); padding-top: 6px; }
/* Éco-participation regulatory mention: a left-aligned muted footnote spanning both cols. */
table.totals tr.eco-note td { color: var(--muted); font-size: var(--fs-12); font-weight: var(--fw-normal); text-align: left; padding-top: 6px; }
/* In-place draft line edit: inputs bound (via the HTML form attribute) to the
   edit form in the actions cell; fill their column, no field-label chrome. */
.line-edit-input { width: 100%; min-width: 56px; margin: 0; }

