/* =============================================================================
   wm-page.css — shared page chrome and list-page primitives.

   One place for the things every page has: the title bar, its action buttons,
   the cards, toolbars, tables and status pills. Values come from the tokens in
   style.css (:root), so a change here or there applies everywhere.

   Loaded AFTER style.css so it takes precedence over the legacy globals without
   needing !important. Page stylesheets should not restate these values; if a
   page needs something different, add a token or a modifier class here rather
   than overriding it locally — that local override is how the invoice pages
   drifted into four different looks.
   ========================================================================== */

/* ---- Page title bar ------------------------------------------------------ */

/* Keep the horizontal inset on `--wm-page-inset` so the heading lines up with
   the table below it — a literal value here is what knocked the two out of
   alignment on every page. Only the vertical padding is this file's business,
   tightening the bar to `--wm-titlebar-min-height`. */
.main-content .main-title {
    min-height: var(--wm-titlebar-min-height);
    padding: 8px var(--wm-page-inset);
}

.main-content .main-title h1 {
    color: var(--dark-txt);
    font-size: var(--wm-page-title-size);
    font-weight: 700;
    margin: 0;
}

/* ---- Title-bar action buttons -------------------------------------------- */

.invoice-header-actions,
.main-title .page-header-actions {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.invoice-header-actions button,
.main-title .page-header-actions button {
    align-items: center;
    border-radius: var(--wm-control-radius);
    box-shadow: none;
    display: inline-flex;
    font-size: var(--wm-font-sm);
    font-weight: var(--wm-weight-strong);
    gap: 6px;
    height: var(--wm-control-height);
    justify-content: center;
    line-height: var(--wm-line-sm);
    padding: var(--wm-control-padding);
}

/* Secondary action */
.invoice-header-actions .normal-btn,
.main-title .page-header-actions .normal-btn {
    background: var(--wm-card-bg);
    border: 1px solid var(--wm-card-border-color);
    color: var(--wm-text-strong);
}

/* Primary action — anything that isn't explicitly secondary */
.invoice-header-actions > button:not(.normal-btn),
.main-title .page-header-actions > button:not(.normal-btn) {
    background: var(--purple);
    border: 1px solid var(--purple);
    color: var(--white);
}

.invoice-header-actions button img,
.main-title .page-header-actions button img {
    height: 16px;
    width: 16px;
}

.invoice-header-actions button p,
.main-title .page-header-actions button p {
    margin: 0;
}

/* ---- Fixed-viewport list pages ------------------------------------------- */

/* Opt-in scheme (`wm-fixed-page` on the page root) that pins the page chrome
   to the viewport: title bar, card toolbar and pagination stay put, and only
   the rows scroll, inside a `wm-table-scroll` wrapper around the <table>.
   Every wrapper between .main-content and the scroll area must pass the
   height down (flex column + min-height: 0), otherwise the chain breaks and
   the page falls back to scrolling as a whole. */
.wm-fixed-page .main-content {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}

/* Title bars, tab strips and any other chrome directly under .main-content
   keep their natural height; the body wrapper below re-enables growing. */
.wm-fixed-page .main-content > * {
    flex-shrink: 0;
}

.wm-fixed-page .main-content .dispatch-list-tab {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.wm-fixed-page .main-content .data-left-right {
    flex: 1;
    min-height: 0;
}

.wm-fixed-page .main-content .data-left-right .data-left {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

/* Tab-button rows and other chrome between the body and the card keep their
   natural height; only the card itself grows. */
.wm-fixed-page .main-content .data-left-right .data-left > .dispatch-tab-btn {
    flex-shrink: 0;
}

/* Some pages put the card inside a tab panel (`dispatch-group-btn-tab`).
   Locations toggles that panel's `display` inline, so it can't be forced to
   flex — give it the height and let the card fill it instead. */
.wm-fixed-page .main-content .data-left-right .data-left > .dispatch-group-btn-tab {
    flex: 1;
    min-height: 0;
}

.wm-fixed-page .main-content .data-left-right .data-left > .dispatch-group-btn-tab .main-table {
    height: 100%;
}

/* The card becomes the flex column that pins its toolbar and pagination;
   scrolling moves off the card onto the wrapper below, overriding the
   `overflow-x: scroll` the legacy `.main-table` rule carries. The legacy
   24px vertical margin goes too — the body padding already insets the card,
   and any extra height would push the pagination off screen. */
.wm-fixed-page .main-content .data-left-right .main-table {
    display: flex;
    flex-direction: column;
    flex: 1;
    margin: 0;
    min-height: 0;
    overflow: hidden;
}

/* Toolbars, tab rows and pagination inside the card keep their natural
   height; the scroll wrapper's own `flex: 1` below re-enables growing. */
.wm-fixed-page .main-table > * {
    flex-shrink: 0;
}

/* Three classes deep so this also beats page-scoped rules on reused
   wrappers (e.g. Offers' `.table-container`, which sets overflow-x only). */
.wm-fixed-page .main-content .wm-table-scroll {
    flex: 1;
    min-height: 0;
    overflow: auto;
    scrollbar-width: thin;
}

/* Column headers already paint an opaque background, so they can float over
   the rows that scroll under them. Targets every th, not `thead th`, because
   some legacy tables (Dispatch) put the header row straight in the table. */
.wm-fixed-page .wm-table-scroll th {
    position: sticky;
    top: 0;
    z-index: 2;
}

/* Collapsed table borders don't travel with sticky cells: the header's 1px
   borders stay behind in the row flow, so the header shifts a pixel on
   scroll and rows glint through the translucent border above it. Separate
   the borders, draw the header's edges as an opaque shadow (#EBEEF1 is the
   legacy #1E293B0F flattened onto the header's #F8FAFC), and move the row
   dividers from <tr> — which only paints in collapse mode — onto the cells.
   Selector depth matches the legacy `.dispatch` table rules so these win on
   specificity, not load order. */
.wm-fixed-page .main-content .data-left-right .main-table .wm-table-scroll table {
    border-collapse: separate;
    border-spacing: 0;
}

.wm-fixed-page .main-content .data-left-right .main-table .wm-table-scroll table tr th {
    border-bottom: 0;
    border-top: 0;
    box-shadow:
        0 1px 0 0 #EBEEF1,
        inset 0 1px 0 0 #EBEEF1;
}

.wm-fixed-page .main-content .data-left-right .main-table .wm-table-scroll table tbody tr td {
    border-bottom: 1px solid #1E293B0F;
}

/* The shift table's own scoped styles already draw a td border-top, which
   keeps painting in separate-borders mode — skip the generic bottom border
   there or every row boundary doubles to 2px. */
.wm-fixed-page .main-content .data-left-right .main-table .wm-table-scroll table.shift-table tbody tr td {
    border-bottom: 0;
}

/* The pagination bar never gives up height to the scroll area. */
.wm-fixed-page .wm-pagination {
    flex-shrink: 0;
}

/* Customer-access tab: its card is a component-scoped class, not
   `.main-table`, so it needs its own link in the height chain. */
.wm-fixed-page .main-content .customer-access-page {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.wm-fixed-page .main-content .customer-access-page > :not(.wm-table-scroll) {
    flex-shrink: 0;
}

/* Customer-dashboard launcher: same idea for its bespoke shell — the page
   body and the panel pass the height down to the table wrapper. */
.wm-fixed-page .main-content .launcher-page,
.wm-fixed-page .main-content .context-panel {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.wm-fixed-page .main-content .launcher-page > :not(.context-panel),
.wm-fixed-page .main-content .context-panel > :not(.wm-table-scroll) {
    flex-shrink: 0;
}

/* ---- Fixed-viewport invoice workspaces ----------------------------------- */

/* The invoice pages render their list through a table component whose cards
   sit inside `.invoice-main-table`, so the height chain continues: component
   root → list card → the scroll wrapper the components already have. The
   toolbar cards and card headers are ordinary flex items and keep their
   natural height because only these links grow. */
.wm-fixed-page .invoice-main-table > .invoice-customer-hourly-workspace,
.wm-fixed-page .invoice-main-table > .hourly-overview-workspace,
.wm-fixed-page .invoice-main-table > .invoice-for-subcontractor-workspace,
.wm-fixed-page .invoice-main-table > .invoice-as-subcontractor-workspace {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.wm-fixed-page .invoice-list-card,
.wm-fixed-page .hourly-overview-card,
.wm-fixed-page .invoice-subcontractor-card {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

/* Three classes deep so this beats the components' scoped
   `.invoice-table-scroll { overflow: visible }` (equal two-class specificity
   but their bundle loads later) — without the win the rows overflow the card
   instead of scrolling. */
.wm-fixed-page .main-content .invoice-table-scroll,
.wm-fixed-page .main-content .hourly-table-scroll {
    flex: 1;
    min-height: 0;
    overflow: auto;
    scrollbar-width: thin;
}

/* Same sticky-header treatment as `.wm-table-scroll` above: separate the
   borders so they travel with the sticky cells, and flatten the header's
   translucent divider (--wm-divider on the card's white) to opaque #EBECED. */
.wm-fixed-page .invoice-table-scroll .wm-table,
.wm-fixed-page .hourly-table-scroll .wm-table {
    border-collapse: separate;
    border-spacing: 0;
}

.wm-fixed-page .invoice-table-scroll .wm-table thead th,
.wm-fixed-page .hourly-table-scroll .wm-table thead th {
    border-bottom: 0;
    box-shadow: 0 1px 0 0 #EBECED;
    position: sticky;
    top: 0;
    z-index: 2;
}

/* ---- Cards --------------------------------------------------------------- */

.wm-card {
    background: var(--wm-card-bg);
    border: 1px solid var(--wm-card-border-color);
    border-radius: var(--wm-card-radius);
    box-shadow: var(--wm-card-shadow);
}

.wm-card-stack {
    display: flex;
    flex-direction: column;
    gap: var(--wm-card-gap);
}

/* ---- Toolbar / card header strip ----------------------------------------- */

.wm-toolbar {
    align-items: center;
    display: flex;
    gap: 16px;
    justify-content: space-between;
    min-height: var(--wm-header-row-height);
    padding: var(--wm-card-padding);
    width: 100%;
}

/* ---- Status pills -------------------------------------------------------- */

.wm-pills {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.wm-pills button {
    background: var(--wm-control-bg);
    border: 1px solid var(--wm-card-border-color);
    border-radius: var(--wm-control-radius);
    color: var(--wm-text-strong);
    font-size: var(--wm-font-sm);
    font-weight: var(--wm-weight-strong);
    line-height: var(--wm-line-sm);
    min-height: var(--wm-control-height);
    padding: var(--wm-control-padding);
}

.wm-pills button.active {
    background: #eef0ff;
    color: var(--purple);
}

/* ---- Invoice workspace shell --------------------------------------------- */

/* The four invoice workspaces (customer, hourly, for-subcontractor,
   as-subcontractor) share one skeleton: title bar, a padded body, and a
   wrapper holding a single table card. They used to carry a copy of these
   rules each, in four scoped stylesheets that each restated all four
   variants — so most of every copy was dead, and the parts that were live
   had drifted apart.

   The page shell itself is NOT restated here. The title bar, the body inset
   and the content max-width all come from `.main-content .main-title-bar` and
   `.main-content .data-left-right` in style.css, exactly as on every other
   page. These pages used to override the body padding to a flat 24px, which
   is why they sat differently from Dispatch, Locations, Users and the rest. */

/* The toolbar and the list are each their own bordered card, so this wrapper
   is a plain box. The invoice page roots deliberately do not carry the
   `dispatch` class: everything `.dispatch` would contribute here is a panel
   these pages then have to cancel, and cancelling it is what forced the deep
   selectors elsewhere. `position`/`z-index` keep the row menus stacking above
   what follows them. */
.invoice-page .main-content .data-left-right .invoice-main-table {
    display: flex;
    flex-direction: column;
    gap: var(--wm-card-gap);
    position: relative;
    z-index: 1;
}

/* Primary "send to e-conomic" action. In a title bar the shared
   `.page-header-actions` rule above already shapes it; this is what it looks
   like in the tables and modals that also use it. */
.invoice-send-economic {
    align-items: center;
    background: var(--purple);
    border: 1px solid var(--purple);
    border-radius: var(--wm-control-radius);
    color: var(--white);
    display: inline-flex;
    font-size: var(--wm-font-sm);
    font-weight: var(--wm-weight-strong);
    gap: 6px;
    height: var(--wm-control-height);
    justify-content: center;
    padding: var(--wm-control-padding);
}

.invoice-send-economic img {
    height: 16px;
    width: 16px;
}

.invoice-send-economic.disabled,
.invoice-send-economic:disabled {
    cursor: not-allowed;
    opacity: .48;
}

/* Accounting-system prompt, shown in the customer title bar only. */
.invoice-connect-pill {
    background: rgba(255, 195, 10, .12);
    border: 0;
    border-radius: var(--wm-control-radius);
    gap: 6px;
    height: var(--wm-control-height);
    max-width: 100%;
    padding: 8px 10px;
}

.invoice-connect-pill img {
    flex: 0 0 16px;
    height: 16px;
    width: 16px;
}

.invoice-connect-pill span {
    color: #b47500;
    display: block;
    font-size: var(--wm-font-sm);
    font-weight: var(--wm-weight-body);
    line-height: var(--wm-line-sm);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The Connect action is an amber inline link inside the pill, not a button —
   it deliberately keeps the pill's warning colour rather than taking the
   primary purple. Four classes so it beats `.main-content .main-title button`
   in style.css, which would otherwise paint it as a primary action. */
.invoice-page .main-title .invoice-connect-pill .invoice-connect-link {
    background: transparent;
    border: 0;
    border-bottom: 1.5px solid #b47500;
    border-radius: 0;
    color: #b47500;
    flex: 0 0 auto;
    font-size: 10px;
    font-weight: var(--wm-weight-strong);
    height: 16px;
    line-height: var(--wm-line-sm);
    padding: 0;
    text-decoration: none;
}

/* ---- Tables -------------------------------------------------------------- */

.wm-table {
    border-collapse: collapse;
    width: 100%;
}

.wm-table thead th {
    background: var(--wm-card-bg);
    border-bottom: 1px solid var(--wm-divider);
    color: var(--wm-text-muted);
    font-size: var(--wm-font-sm);
    font-weight: var(--wm-weight-strong);
    height: var(--wm-th-height);
    letter-spacing: normal;
    line-height: var(--wm-line-sm);
    padding: var(--wm-cell-padding);
    text-transform: none;
    white-space: nowrap;
}

.wm-table tbody td {
    border-bottom: 1px solid var(--wm-divider-soft);
    color: var(--wm-text-body);
    font-size: var(--wm-font-md);
    font-weight: var(--wm-weight-body);
    height: var(--wm-td-height);
    line-height: var(--wm-line-md);
    padding: var(--wm-cell-padding);
    vertical-align: middle;
}
/* Options in the manual-registration and archive-linked prompts: the same
   invoice-check square used by the invoice tables, instead of a bare browser
   checkbox. The whole row toggles. */
.invoice-prompt-option {
    align-items: flex-start;
    cursor: pointer;
    display: flex;
    gap: 10px;
    /* WMPopup's body has no padding of its own; match the 16px inset the
       bootstrap modal-header gives the title above. */
    padding-left: 16px;
    padding-right: 16px;
}
.invoice-prompt-option .invoice-check {
    align-items: center;
    background: #ffffff;
    border: 1px solid #cbd5e1;
    border-radius: 5px;
    display: inline-flex;
    flex: 0 0 auto;
    height: 16px;
    justify-content: center;
    margin-top: 2px;
    padding: 0;
    width: 16px;
}
.invoice-prompt-option .invoice-check.checked {
    background: #5263ff;
    border-color: #5263ff;
}
.invoice-prompt-option .invoice-check.checked::after {
    border: solid #ffffff;
    border-width: 0 2px 2px 0;
    content: "";
    height: 9px;
    margin-top: -2px;
    transform: rotate(45deg);
    width: 5px;
}

/* ---- Complaints table embedded in a modal ------------------------------- */

/* The complaints table is also shown inside the location modal and the subcontractor
   slider. Those hosts supply `.dispatch .main-content` purely so the app's table styling
   resolves, so everything that class carries for a full page has to come back off: the
   240px sidebar offset, the viewport-height floor and the page background. */
.complaints-embed .main-content {
    margin-left: 0;
    min-height: 0;
    background-color: transparent;
}

/* The page gutter and centred page width go: the hosting tab already insets its content
   horizontally, and doubling it would squeeze the table. The vertical padding stays —
   without it the card butts straight against the tab strip above and the panel below. */
.complaints-embed .main-content .data-left-right {
    padding: 16px 0;
    max-width: none;
    margin: 0;
}

.complaints-embed .main-content .data-left-right .main-table {
    margin: 0;
}

/* The page tables carry `min-width: 1000px`, which is wider than a modal tab: it pushed the
   last column out of sight behind a scrollbar the legacy card deliberately hides. Four
   columns fit a tab on their own, so let them. */
.complaints-embed .main-content .data-left-right .main-table table {
    min-width: 0;
}

.complaints-embed .main-content .wm-table-scroll {
    max-height: min(52vh, 460px);
    overflow: auto;
    scrollbar-width: thin;
}

/* Same sticky header as the fixed-viewport pages; the rule there is scoped to
   `.wm-fixed-page`, which a modal never carries. */
.complaints-embed .wm-table-scroll th {
    position: sticky;
    top: 0;
    z-index: 2;
}
