/* ═══════════════════════════════════════════════════════════════════
   Invoices tab (AdminInvoices.vue) - `inv-`.

   A fourth data tab of /admin/payments. Inherits RTL from `.pay-page`
   (admin-payments.css), so nothing here re-declares direction; the
   component wraps every money figure, date, document number and email
   in `dir="ltr"` itself.

   Like `.pay-panel--cards` and `.pay-panel--links`, the panel must never
   gain `overflow`, `transform`, `filter`, `backdrop-filter`,
   `perspective`, `contain` or `will-change`: the toast inside it is
   `position: fixed`, and this screen also hosts three date-range
   pickers whose desktop popover and phone sheet are fixed too. Any one
   of those properties makes the panel their containing block, which
   clips the popover and unanchors the sheet. The table does its own
   scrolling inside `.inv-table-wrap`.

   Shared chrome (`.admin-table`, `.btn`, `.btn-icon`, `.empty-state`,
   `.toast`, `.admin-toolbar`, `.modal*`, `.reg-filter-bar`,
   `.reg-th-sort`, `.form-*`) comes from admin.css; only what is
   specific to this screen lives here. Shadows use the cool-blue
   rgba(0, 60, 130, *) family, never raw black.

   This file MUST keep its `admin` filename prefix: scripts/bundle-css.mjs
   partitions the two production bundles on `href.startsWith('/css/admin')`,
   so a rename ships it to every marketing visitor.
   ═══════════════════════════════════════════════════════════════════ */

/* Declared here rather than in admin-payments.css beside its two
   siblings because this sheet loads after it, so the two never race -
   and everything this screen owns then lives in one file. */
.pay-panel--invoices {
  min-width: 0;
}

/* ── Head ── */

.inv-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 0.9rem;
}

/* global.css only dims .btn-primary/.btn-secondary when disabled; the plain
   .btn.btn-sm here matched neither, so a dead button looked clickable (found in
   the visual pass). Same treatment admin-leads.css gives its own.

   Scoped to the TAB ROOT rather than to a list of containers: the pager's
   "הקודם" is disabled on every first page, and the stale banner's retry and both
   modal footers are disabled while their request is in flight. `.inv-panel` is
   the single root of this tab and nothing here is teleported, so this cannot
   reach another admin screen. */
.inv-panel .btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

.inv-subtitle {
  flex: 1 1 30rem;
  margin: 0;
  max-width: 84ch;
  color: var(--text-secondary);
  font-size: 0.9rem;
  line-height: 1.6;
}

.inv-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  max-width: 56ch;
  margin-inline: auto;
  line-height: 1.6;
}

.inv-error p {
  margin: 0;
}

/* ── Filters ──
   Ten controls, so the bar wraps rather than compressing them; the
   search field is the one that takes the leftover width. */

.inv-filter-bar {
  row-gap: 0.6rem;
}

.inv-amount-input {
  width: 7rem;
  font-variant-numeric: tabular-nums;
}

/* ── The search box ──
   Shared by BOTH tabs of /admin/payments that use this kit: the invoices
   filter bar and the deposits one (`.admin-search.inv-search`, the only two
   call sites). It carried nothing but a width, so it rendered as the browser's
   own control - a 20px-tall box with a 2px inset border and square corners,
   standing beside a 39px rounded date trigger and multi-selects, at the 13.3px
   default that trips iOS Safari's 16px focus-zoom floor.

   Deliberately the same numbers as the transactions tab's own box
   (`.cpay-search`, admin-card-payments.css), which fixed the identical defect
   first: the three search fields of this screen must be interchangeable.

   Scoped to `.inv-search` rather than `.admin-search` so it wins over the base
   rules in admin.css without !important, and reaches neither the leads,
   registrations, enrollments nor contracts boxes, which mirror their own way. */

.inv-search input {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  min-height: 2.45rem;
  padding-right: 2.1rem;
  padding-left: 2.25rem;
  background: #fff;
  border: 1px solid #e6ebf2;
  border-radius: 10px;
  font-family: inherit;
  font-size: 0.85rem;
  color: #191A23;
  direction: rtl;
  text-align: right;
  text-overflow: ellipsis;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  -webkit-appearance: none;
  appearance: none;
}

.inv-search input::placeholder {
  color: #8E8F9E;
  opacity: 1;
}

.inv-search input:hover {
  border-color: rgba(0, 113, 227, 0.35);
}

/* The ring the date-range trigger and the transactions search both use, so
   every control in the bar focuses identically. */
.inv-search input:focus {
  border-color: var(--primary-color);
  box-shadow: 0 0 0 3px rgba(0, 113, 227, 0.12);
}

/* type="search" ships a native clear button in WebKit that would sit beside
   ours and clear the field without telling Vue. */
.inv-search input::-webkit-search-cancel-button,
.inv-search input::-webkit-search-decoration {
  -webkit-appearance: none;
  appearance: none;
}

/* admin.css anchors both glyphs physically (magnifier left, clear right),
   which on this RTL screen put the magnifier at the END of the line and the
   clear button on top of where the Hebrew text starts. Mirrored, so the
   magnifier leads the line and the clear button closes it. Change these two
   and the touch-target padding in the <=1024px block below moves side too. */
.inv-search .fa-search {
  right: 0.75rem;
  left: auto;
  color: #8E8F9E;
}

.inv-search .search-clear {
  left: 0.4rem;
  right: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  color: #8E8F9E;
}

.inv-search .search-clear:hover {
  background: rgba(0, 113, 227, 0.08);
  color: #191A23;
}

.inv-clear {
  align-self: flex-end;
}

/* Said when the cohort list itself failed to load, so the picker beside
   it cannot be read as "there are no cohorts". */
.inv-filter-note {
  display: block;
  margin-block-start: 0.25rem;
  padding: 0;
  background: none;
  border: none;
  color: #8A5A12;
  font-size: 0.72rem;
  text-align: start;
  cursor: pointer;
}

.inv-filter-note:hover {
  text-decoration: underline;
}

/* A cohort filter that arrived with a shared link, shown to a reader who
   has no access to the cohort list and so cannot be offered the picker. */
.inv-filter-locked {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  height: 2.1rem;
  padding-inline: 0.6rem;
  background: #F4F6FA;
  border: 1px solid #dfe4ec;
  border-radius: 8px;
}

.inv-filter-locked-name {
  font-size: 0.82rem;
  color: #5A5B6A;
}

.inv-filter-locked-clear {
  padding: 0;
  background: none;
  border: none;
  color: #8a93a3;
  cursor: pointer;
}

.inv-filter-locked-clear:hover {
  color: #C4551A;
}

/* ── The page-scoped summary line ── */

.inv-summary {
  margin: 0 0 0.6rem;
  font-size: 0.84rem;
  color: #5A5B6A;
  font-variant-numeric: tabular-nums;
}

/* ── Stale wash ──
   One class for every block rendered from the last payload. Dimming a
   subset is worse than dimming nothing: the un-dimmed half reads as the
   authoritative one while the rest says otherwise. */

.inv-stale {
  opacity: 0.55;
  filter: saturate(0.7);
}

.inv-stale-banner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
  padding: 0.6rem 0.9rem;
  background: #FDF6E7;
  border: 1px solid #EDD9A3;
  border-radius: var(--radius-sm);
  color: #7A5C10;
  font-size: 0.85rem;
  line-height: 1.6;
}

/* ── Table ── */

.inv-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}

.inv-table {
  min-width: 1420px;
}

.inv-table th,
.inv-table td {
  white-space: nowrap;
  vertical-align: top;
}

.inv-td-person {
  font-weight: 600;
  color: #191A23;
}

.inv-person-link {
  color: var(--primary-color);
  text-decoration: none;
}

.inv-person-link:hover {
  text-decoration: underline;
}

.inv-sub {
  display: block;
  margin-block-start: 0.15rem;
  font-weight: 400;
  font-size: 0.74rem;
  color: #8E8F9E;
}

.inv-td-cohort {
  color: #5A5B6A;
}

.inv-td-amount,
.inv-td-day {
  font-variant-numeric: tabular-nums;
}

.inv-td-amount {
  font-weight: 600;
  color: #191A23;
}

/* Which instalment of the charge this row is. The whole reason this table
   has more rows than the payments ledger does, so it sits next to the
   figure rather than in a column of its own. */
.inv-chip-inst {
  display: inline-block;
  margin-inline-start: 0.35rem;
  padding: 0.05rem 0.35rem;
  background: #EAF2FD;
  border-radius: 999px;
  color: #0B5CC4;
  font-weight: 500;
  font-size: 0.7rem;
}

.inv-sku {
  font-size: 0.82rem;
  color: #5A5B6A;
}

.inv-sku--none {
  color: #8E8F9E;
}

/* The deadline column carries the warning too, not only the chip two
   columns over: this is the column a reader scans when asking "what is
   about to be late". */
.inv-due-date {
  color: #B3261E;
  font-weight: 600;
}

/* ── Status chip ──
   `לטיפול` is the only FILLED chip on the screen. It means the money is
   in the bank account and the fourteen-day statutory clock is running
   with no document issued, which is the one state this table exists to
   surface - so it is deliberately louder than every other state,
   including the failures. */

.inv-chip {
  display: inline-block;
  padding: 0.14rem 0.5rem;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 500;
  line-height: 1.5;
  white-space: nowrap;
}

.inv-chip--due {
  background: #B3261E;
  color: #fff;
  font-weight: 600;
}

.inv-chip--not_due {
  background: #EEF0F4;
  color: #6E7180;
}

.inv-chip--issued {
  background: #E7F6ED;
  color: #1B7F4C;
}

.inv-chip--reconciled {
  background: #EAF2FD;
  color: #0B5CC4;
}

.inv-chip--failed {
  background: #FDECEC;
  color: #A32020;
  box-shadow: inset 0 0 0 1px #F3C4C0;
}

.inv-chip--ambiguous {
  background: #FDF3E3;
  color: #8A5A12;
  box-shadow: inset 0 0 0 1px #EDD9A3;
}

.inv-chip--refund {
  background: #F1ECFD;
  color: #5B3BC4;
}

.inv-chip--excluded {
  background: #EEF0F4;
  color: #6E7180;
  box-shadow: inset 0 0 0 1px #dfe4ec;
}

/* The row itself, so a long table can be scanned without reading chips.
   Keyed on the same status the chip is, and kept pale enough that the
   chip stays the loud thing. */
.inv-row--due td {
  background: #FFF7F5;
}

/* ── Document number and the duplicate marker ── */

.inv-td-doc {
  font-variant-numeric: tabular-nums;
}

/* More than one legal document points at this instalment. Never quiet:
   two running numbers for the same money is a correction an accountant
   has to make, and the only fix is a credit note. */
.inv-dup {
  display: inline-block;
  margin-inline-start: 0.3rem;
  padding: 0.05rem 0.32rem;
  background: #FDECEC;
  border-radius: 999px;
  color: #A32020;
  font-weight: 600;
  font-size: 0.68rem;
}

/* ── Email outcome ── */

.inv-td-email {
  font-size: 0.8rem;
  color: #5A5B6A;
}

.inv-email {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.inv-email--sent {
  color: #1B7F4C;
}

.inv-email--pending {
  color: #0B5CC4;
}

.inv-email--failed,
.inv-email--no_transport {
  color: #A32020;
}

.inv-email--no_address {
  color: #8A5A12;
}

.inv-email--not_applicable,
.inv-email--none {
  color: #8E8F9E;
}

/* ── Row actions ──
   Labelled, never icon-only. A glyph cannot say whether the customer
   gets the document by email, and it cannot say that one of these
   buttons creates a legal number that can never be deleted. */

.inv-col-actions {
  width: 1%;
}

.inv-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.3rem;
}

/* ── Pagination ── */

.inv-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-block-start: 0.9rem;
}

.inv-pagination-mid {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.inv-pagination-info {
  font-size: 0.84rem;
  color: #5A5B6A;
}

.inv-page-size {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8rem;
  color: #8E8F9E;
}

.inv-page-size-select {
  padding: 0.2rem 0.4rem;
  border: 1px solid #dfe4ec;
  border-radius: 6px;
  background: #fff;
  font-size: 0.8rem;
  font-family: inherit;
}

/* ── Modals ── */

.inv-modal {
  width: 640px;
}

.inv-modal-lead {
  margin: 0 0 1rem;
  color: #5A5B6A;
  font-size: 0.88rem;
  line-height: 1.7;
}

.inv-report {
  width: 860px;
}

/* A scan that stopped before the end of Morning's documents. Louder than the
   stale banner on purpose: the report below it can be read as a to-do list, and
   issuing off an incomplete one mints a second legal number. */
.inv-report-truncated {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  margin-bottom: 1.1rem;
  padding: 0.8rem 1rem;
  background: #FCEDEC;
  border: 1px solid #E9B4AF;
  border-inline-start: 4px solid #B3261E;
  border-radius: var(--radius-sm);
  color: #7A1C16;
  font-size: 0.85rem;
  line-height: 1.65;
}

.inv-report-truncated > i {
  margin-block-start: 0.15rem;
  color: #B3261E;
}

.inv-report-truncated-title {
  margin: 0 0 0.25rem;
  font-size: 0.92rem;
  font-weight: 600;
}

.inv-report-truncated-text {
  margin: 0;
}

.inv-report-counts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1.1rem;
}

.inv-report-count {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 8rem;
  padding: 0.6rem 0.8rem;
  background: #F7F9FC;
  border: 1px solid #e6ebf2;
  border-radius: 10px;
}

.inv-report-count-of {
  font-size: 0.9rem;
  font-weight: 400;
  color: #8a93a3;
}

.inv-report-count-value {
  font-size: 1.35rem;
  font-weight: 600;
  color: #191A23;
  font-variant-numeric: tabular-nums;
}

.inv-report-count-label {
  font-size: 0.74rem;
  color: #8a93a3;
}

.inv-report-count--warn .inv-report-count-value {
  color: #8A5A12;
}

.inv-report-count--due .inv-report-count-value {
  color: #B3261E;
}

.inv-report-section {
  margin-block-start: 1.1rem;
}

.inv-report-title {
  margin: 0 0 0.5rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: #191A23;
}

.inv-report-empty {
  margin: 0;
  color: #8E8F9E;
  font-size: 0.85rem;
}

.inv-report-table {
  width: 100%;
  font-size: 0.82rem;
}

.inv-report-table td {
  vertical-align: top;
  white-space: normal;
}

/* ═══════════════════════════════════════════════════════════════════
   Tablet / phone: rows become cards.

   Twelve columns do not fit below 1024px and the generic .admin-table
   rules crush them into an overlap, so each cell prints its own
   data-label caption instead - the same treatment .cpay-table and
   .apl-table get. An empty labelled cell hides itself, so a row with no
   document grows no blank "מספר מסמך" line.
   ═══════════════════════════════════════════════════════════════════ */

@media (max-width: 1024px) {
  .inv-table-wrap {
    overflow-x: visible;
  }

  .inv-table {
    display: block;
    min-width: 0;
    background: transparent;
    border: none;
    box-shadow: none;
  }

  .inv-table thead {
    display: none;
  }

  .inv-table tbody {
    display: block;
    width: 100%;
  }

  .inv-table tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.2rem 0.7rem;
    width: 100%;
    margin-block-end: 0.85rem;
    padding: 0.8rem 1rem 0.65rem;
    background: #fff;
    border: 1px solid #e6ebf2;
    border-radius: 14px;
    box-shadow: 0 1px 3px rgba(0, 60, 130, 0.05);
  }

  /* The row tint is a cell background on the desktop table; on a card the
     card itself is what carries it.

     This used to be keyed on `.inv-row--due`, which no template has
     written since the table started tagging rows by PHASE - so the phone
     marked nothing at all, while the desktop cells kept a tint the white
     card underneath contradicted. Keyed on the live class now, and
     raised with its desktop twin: the start bar becomes the card's own
     left edge. */
  .inv-table tbody tr.inv-payment--deposited_uninvoiced {
    background: #FDE7E3;
    border-color: #E39A92;
    border-inline-start-width: 3px;
    border-inline-start-color: #B3261E;
  }

  .inv-table tbody tr:hover td,
  .inv-table tbody tr.inv-payment--deposited_uninvoiced td {
    background: transparent;
  }

  /* The bar is the card's border here, not a cell edge - the cells are no
     longer laid out as columns. */
  .inv-table tbody tr.inv-payment--deposited_uninvoiced td:first-child {
    border-inline-start: none;
  }

  .inv-table td {
    white-space: normal;
    border: none;
    padding: 0;
  }

  /* Name and cohort lead the card unlabelled - a caption above the name
     would only repeat it, and that is also what keeps the two out of the
     generic `td[data-label]` rule below, which would otherwise beat their
     own ordering on equal specificity. Everything else stacks as a
     labelled row, and the actions land last. */
  .inv-table td.inv-td-person {
    order: 0;
    flex: 1 1 auto;
    font-size: 1rem;
  }

  .inv-table td.inv-td-cohort {
    order: 2;
    flex: 1 1 100%;
    font-size: 0.82rem;
  }

  .inv-table td[data-label] {
    order: 3;
    flex: 1 1 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.6rem;
    padding-block: 0.34rem;
    border-block-start: 1px solid #f1f4f8;
  }

  .inv-table td[data-label]:empty {
    display: none;
  }

  .inv-table td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 8rem;
    color: #8a93a3;
    font-weight: 600;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    line-height: 1.7;
  }

  .inv-table td.inv-col-actions {
    order: 4;
    width: auto;
    flex: 1 1 100%;
    padding-block-start: 0.5rem;
    border-block-start: 1px solid #f1f4f8;
  }

  /* A reader with no write grant, or a row whose only controls are writes, gets
     no buttons at all - and the rule above would leave a stray divider line
     under the card. `td[data-label]:empty` cannot cover this one: the cell is
     not labelled, and it is never truly `:empty` either. */
  .inv-table td.inv-col-actions:not(:has(button)) {
    display: none;
  }

  .inv-report,
  .inv-modal,
  /* Named beside `.inv-modal` rather than relying on it: `.inv-mark` sets its
     own width further down the file, at the same specificity, so it would win
     this override on source order alone. */
  .inv-mark {
    width: auto;
  }

  /* ── Touch floors (admin mobile revamp) ──
     44px targets and 16px input text below 1025px. 16px exactly on text
     inputs: anything smaller makes iOS Safari zoom the whole page on
     focus. The issue buttons stay labelled - only their hit area grows. */
  .inv-panel .btn,
  .inv-panel .btn-icon {
    min-height: 44px;
    min-width: 44px;
  }

  .inv-panel .form-input,
  .inv-panel .form-select,
  .inv-panel .inv-page-size-select {
    font-size: 16px;
    min-height: 44px;
  }

  /* Touch floors for the search box, on the shared class so the deposits tab
     gets them from here too (`.inv-panel` would have missed it). 16px exactly
     on the input: anything smaller makes iOS Safari zoom the page on focus and
     it never zooms back out. 2.75rem = 44px. The padding grows on the LEFT,
     the side the clear button now sits on. */
  .inv-search input {
    min-height: 2.75rem;
    padding-left: 3.3rem;
    font-size: 16px;
  }

  .inv-search .search-clear {
    width: 2.75rem;
    height: 2.75rem;
    left: 0.25rem;
  }

  .inv-filter-note {
    min-height: 44px;
  }

  .inv-filter-locked {
    height: auto;
    min-height: 44px;
  }

  .inv-filter-locked-clear {
    min-width: 44px;
    min-height: 44px;
  }
}

@media (max-width: 767px) {
  .inv-amount-input {
    width: 100%;
  }

  .inv-pagination {
    gap: 0.5rem;
  }

  .inv-pagination-info {
    order: 3;
    flex: 1 1 100%;
    text-align: center;
  }

  .inv-report-count {
    flex: 1 1 40%;
    min-width: 0;
  }
}

/* ── Print ──
   The reconciliation report is the pre-go-live document the owner hands
   to an accountant, so `העתקת הדוח` (plain text on the clipboard) is the
   primary route out of this screen. These rules only stop a browser
   print from CLIPPING it: the overlay is fixed and scrolls internally,
   which prints as a single cropped page. The panel behind it still
   prints; hiding it would mean reaching outside this screen's own
   subtree. */
@media print {
  .inv-report-overlay {
    position: static;
    background: none;
  }

  .inv-report-overlay .modal {
    width: 100%;
    max-width: none;
    max-height: none;
    overflow: visible;
    box-shadow: none;
  }

  .inv-no-print {
    display: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   Installment invoicing (2026-08-26): the shared components under
   src/components/admin/invoicing/ and the reworked payments tab.

   `.inv-it` is the installments table (one row per slot), mounted by
   the payments-tab expander, the deposits report, the Telepay expander
   and the person card. `.inv-phase` is the PRIMARY chip (the owner's
   five buckets); `.inv-fine` is the secondary one. `.inv-strip` is the
   D18 totals band. `.inv-preview` is the mandatory preview modal (single,
   bulk and credit-note). `.inv-bulk-bar` is the selection bar.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Reconcile banner (D14) ── */

.inv-reconcile-banner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 0.75rem;
  padding: 0.65rem 0.9rem;
  background: #FDF6E7;
  border: 1px solid #EDD9A3;
  border-inline-start: 4px solid #C98A12;
  border-radius: var(--radius-sm);
  color: #7A5C10;
  font-size: 0.86rem;
  line-height: 1.6;
}

.inv-reconcile-banner > i {
  color: #C98A12;
}

.inv-reconcile-banner span {
  flex: 1 1 24rem;
}

/* ── Data strip (D18) ── */

.inv-strip {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 0.55rem;
  margin-bottom: 0.9rem;
}

.inv-strip-card {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
  padding: 0.55rem 0.75rem;
  background: rgba(255, 255, 255, 0.86);
  border: 1px solid #e6ebf2;
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0, 60, 130, 0.05);
  backdrop-filter: saturate(1.2) blur(6px);
}

.inv-strip-label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #6E7180;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.inv-strip-value {
  font-size: 1.25rem;
  font-weight: 600;
  color: #191A23;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}

.inv-strip-sum {
  font-size: 0.78rem;
  color: #5A5B6A;
  font-variant-numeric: tabular-nums;
}

.inv-strip-card--deposited_uninvoiced { border-inline-start: 3px solid #B3261E; }
.inv-strip-card--future { border-inline-start: 3px solid #8E8F9E; }
.inv-strip-card--deposited_invoiced { border-inline-start: 3px solid #1B7F4C; }
.inv-strip-card--refund_uncredited { border-inline-start: 3px solid #8A5A12; }
.inv-strip-card--refund_credited { border-inline-start: 3px solid #5B3BC4; }
.inv-strip-card--overdue { border-inline-start: 3px solid #E9B4AF; }
.inv-strip-card--next { border-inline-start: 3px solid #0B5CC4; }

/* The legal deadline is the one figure that may not read calm. */
.inv-strip-card--hot {
  background: #FCEDEC;
  border-color: #E9B4AF;
  border-inline-start-color: #B3261E;
}

.inv-strip-card--hot .inv-strip-value {
  color: #B3261E;
}

.inv-strip-demo-note {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 0.78rem;
  color: #8E8F9E;
}

/* ── Phase chip (primary) and fine chip (secondary) ── */

.inv-phase {
  display: inline-block;
  padding: 0.14rem 0.55rem;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

/* The one FILLED chip: money in the bank, no document, clock running. */
.inv-phase--deposited_uninvoiced {
  background: #B3261E;
  color: #fff;
}

.inv-phase--future {
  background: #EEF0F4;
  color: #6E7180;
}

.inv-phase--deposited_invoiced {
  background: #E7F6ED;
  color: #1B7F4C;
}

.inv-phase--refund_uncredited {
  background: #FDF3E3;
  color: #8A5A12;
  box-shadow: inset 0 0 0 1px #EDD9A3;
}

.inv-phase--refund_credited {
  background: #F1ECFD;
  color: #5B3BC4;
}

.inv-fine {
  display: inline-block;
  margin-inline-start: 0.3rem;
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 500;
  line-height: 1.5;
  white-space: nowrap;
  background: #EEF0F4;
  color: #6E7180;
}

.inv-fine--failed { background: #FDECEC; color: #A32020; }
.inv-fine--ambiguous { background: #FDF3E3; color: #8A5A12; }
.inv-fine--in_progress { background: #EAF2FD; color: #0B5CC4; }
.inv-fine--cancelled { background: #1f2937; color: #f3f4f6; }
.inv-fine--expedited { background: #EAF2FD; color: #0B5CC4; }
.inv-fine--enrollment { background: #FDF3E3; color: #8A5A12; box-shadow: inset 0 0 0 1px #EDD9A3; }
.inv-fine--future { background: #EEF0F4; color: #6E7180; }
.inv-fine--credited { background: #F1ECFD; color: #5B3BC4; }

/* ── The installments table ── */

.inv-it-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}

.inv-it {
  width: 100%;
  min-width: 1100px;
  font-size: 0.84rem;
}

.inv-it th,
.inv-it td {
  white-space: nowrap;
  vertical-align: top;
}

.inv-it--compact .inv-it {
  min-width: 960px;
  font-size: 0.8rem;
}

.inv-it--compact .inv-it th,
.inv-it--compact .inv-it td {
  padding-block: 0.4rem;
}

.inv-it-th-check,
.inv-it-td-check {
  width: 2rem;
}

.inv-it-td-person {
  font-weight: 600;
  color: #191A23;
}

.inv-it-td-amount,
.inv-it-td-day,
.inv-it-td-inst {
  font-variant-numeric: tabular-nums;
}

.inv-it-td-amount {
  font-weight: 600;
  color: #191A23;
}

.inv-it-negative {
  color: #8A5A12;
}

.inv-it-future {
  color: #8E8F9E;
}

.inv-it-inst {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  background: #EAF2FD;
  border-radius: 999px;
  color: #0B5CC4;
  font-weight: 600;
  font-size: 0.74rem;
}

.inv-it-refund-tag {
  margin-inline-start: 0.3rem;
  font-size: 0.7rem;
  color: #8A5A12;
}

.inv-it-td-method {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.4rem;
  max-width: 14rem;
}

/* D15: the raw Telepay brand code, so Diners can be spotted by eye. */
.inv-it-brand {
  padding: 0.02rem 0.4rem;
  background: #F4F6FA;
  border: 1px solid #dfe4ec;
  border-radius: 999px;
  font-size: 0.68rem;
  color: #5A5B6A;
  font-variant-numeric: tabular-nums;
}

.inv-it-last4 {
  font-size: 0.74rem;
  color: #8E8F9E;
  font-variant-numeric: tabular-nums;
}

.inv-it-td-status {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  max-width: 18rem;
}

.inv-it-invoice-name {
  display: block;
  font-weight: 500;
  color: #191A23;
}

.inv-it-taxid {
  display: inline-block;
  margin-inline-start: 0.35rem;
  font-size: 0.74rem;
  color: #5A5B6A;
  font-variant-numeric: tabular-nums;
}

.inv-it-td-docs {
  font-variant-numeric: tabular-nums;
}

.inv-it-doc {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.2rem 0.4rem;
  padding-block: 0.1rem;
}

.inv-it-doc + .inv-it-doc {
  border-block-start: 1px dashed #e6ebf2;
}

.inv-it-doc-type {
  font-size: 0.7rem;
  color: #8E8F9E;
}

.inv-it-doc-number {
  font-weight: 600;
  color: #191A23;
}

.inv-it-doc--cancelled .inv-it-doc-number {
  text-decoration: line-through;
  color: #8E8F9E;
}

/* A 320 one of our credit notes reversed: struck through in the credit
   purple, so it reads as "reversed by us", not "cancelled at Morning". */
.inv-it-doc--credited .inv-it-doc-number {
  text-decoration: line-through;
  color: #5B3BC4;
}

.inv-it-doc--credit .inv-it-doc-number {
  color: #5B3BC4;
}

.inv-it-doc-btn {
  width: 1.7rem;
  height: 1.7rem;
  min-width: 0;
  min-height: 0;
  padding: 0;
  font-size: 0.8rem;
}

.inv-it-doc-email {
  font-size: 0.72rem;
}

.inv-it-col-actions {
  width: 1%;
}

.inv-it-sync {
  color: #5A5B6A;
}

.inv-it-note {
  font-size: 0.76rem;
  color: #8E8F9E;
}

.inv-it-empty {
  text-align: center;
  color: #8E8F9E;
  padding-block: 1rem;
}

.inv-it-row--selected td {
  background: #EAF2FD;
}

.inv-it-row--deposited_uninvoiced td {
  background: #FFF7F5;
}

.inv-it-row--busy td {
  opacity: 0.7;
}

/* ── Selection bar (D16) ── */

.inv-bulk-bar {
  position: sticky;
  top: 0;
  z-index: 20;
}

.inv-bulk-issue {
  font-weight: 600;
}

/* ── The preview modal (single, bulk, credit note) ── */

/* The PDF pane is sized from the HEIGHT down, not the width across. The frame
   opens Chrome's viewer at fit-width with its own toolbar off (see
   invoicing/pdfViewer.ts), so the page fills the frame edge to edge and an A4
   sheet is exactly 1.4143x as tall as the frame is wide. Working out the widest
   page whose FULL height still fits the viewport is therefore what puts the
   whole invoice on screen at once instead of its top two thirds - and the modal
   width follows from the same number, so no empty gutter opens beside it.
   The 13rem taken off 94vh is the modal's own furniture: header, footer and
   body padding. `.inv-preview-frame` carries the ratio itself, a hair loose so
   a rounded pixel can never bring back a scrollbar. */
.inv-preview {
  --inv-pdf-w: clamp(20rem, calc((94vh - 13rem) / 1.4143), 56rem);
  --inv-side-w: 19rem;
  width: min(96vw, calc(var(--inv-pdf-w) + var(--inv-side-w) + 4.25rem));
  max-width: 96vw;
  display: flex;
  flex-direction: column;
  max-height: 94vh;
}

/* Bulk: the first document is a TEMPLATE for the shape of the rest, and the
   table under it is what the reader actually studies. A whole page, smaller,
   and a modal sized for seven columns. */
.inv-preview--bulk {
  --inv-pdf-w: clamp(15rem, calc(46vh / 1.4143), 30rem);
  width: min(96vw, 60rem);
}

/* Bulk's page is capped well below what its (table-sized) modal is wide, so
   the pane column is pinned to the page instead of being a free 1fr - the
   leftover width goes to the facts beside it rather than to a gutter of white
   around the document. Restored to one column under 1024px with the rest. */
.inv-preview--bulk .inv-preview-grid {
  grid-template-columns: var(--inv-pdf-w) minmax(0, 1fr);
}

.inv-preview .modal-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.inv-preview-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--inv-side-w);
  gap: 1.25rem;
}

.inv-preview-pane {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.inv-preview-caption {
  margin: 0;
  font-size: 0.8rem;
  color: #5A5B6A;
}

.inv-preview-frame {
  inline-size: min(100%, var(--inv-pdf-w));
  block-size: auto;
  aspect-ratio: 1 / 1.42;
  margin-inline: auto;
  border: 1px solid #e6ebf2;
  border-radius: 10px;
  background: #F4F6FA;
}

.inv-preview-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  /* Stands in the frame's exact box: the modal must not jump when the PDF lands. */
  inline-size: min(100%, var(--inv-pdf-w));
  aspect-ratio: 1 / 1.42;
  margin-inline: auto;
  min-height: 14rem;
  padding: 1rem;
  background: #F7F9FC;
  border: 1px dashed #dfe4ec;
  border-radius: 10px;
  color: #5A5B6A;
  font-size: 0.88rem;
  text-align: center;
}

.inv-preview-state p {
  margin: 0;
}

.inv-preview-state--error {
  color: #A32020;
  border-color: #F3C4C0;
  background: #FDECEC;
}

/* ── Where the document cannot be shown in the page ──
   No phone or tablet browser renders a PDF inside a frame (see
   invoicing/pdfViewer.ts), so on those the frame is never mounted and this card
   stands in its place, offering the browser's OWN viewer instead. The A4 box
   above is sized to hold a whole page; with no page to hold, keeping it would
   leave 500px of empty card on a 390px screen and push the acknowledgement
   checkbox that gates Approve far below the fold. The loading and error states
   collapse with it so the pane never jumps between them.
   Keyed off the modal class, NOT a width query: the switch is decided by the
   platform, and a phone in landscape is wider than the mobile breakpoint. */
.inv-preview--offsite .inv-preview-state {
  aspect-ratio: auto;
  min-height: 0;
  padding: 1.25rem 1rem;
}

.inv-preview-offsite {
  background: #F4F8FE;
  border-style: solid;
  border-color: #D8E6FA;
  color: #191A23;
}

.inv-preview-offsite-icon {
  font-size: 1.6rem;
  color: var(--primary-color);
}

.inv-preview-offsite-note {
  font-size: 0.78rem;
  color: #5A5B6A;
}

.inv-preview-side {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  min-width: 0;
}

.inv-preview-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 0.8rem;
  margin: 0;
  padding: 0.75rem 0.9rem;
  background: #F7F9FC;
  border: 1px solid #e6ebf2;
  border-radius: 10px;
  font-size: 0.86rem;
}

.inv-preview-fact {
  display: contents;
}

.inv-preview-facts dt {
  color: #6E7180;
  font-weight: 500;
}

.inv-preview-facts dd {
  margin: 0;
  color: #191A23;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.inv-preview-legal {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.6;
  color: #5A5B6A;
}

.inv-preview-check {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.88rem;
  cursor: pointer;
}

.inv-preview-check input {
  margin-block-start: 0.2rem;
  flex: 0 0 auto;
}

.inv-preview-check--ack {
  margin-block-start: 0.4rem;
  font-weight: 600;
}

/* The money is not in yet: loud, and the checkbox lives inside it. */
.inv-preview-future {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.7rem 0.9rem;
  background: #FDF3E3;
  border: 1px solid #EDD9A3;
  border-inline-start: 4px solid #C98A12;
  border-radius: var(--radius-sm);
  color: #7A5C10;
  font-size: 0.85rem;
  line-height: 1.6;
}

.inv-preview-future > i {
  margin-block-start: 0.2rem;
  color: #C98A12;
}

.inv-preview-future-text {
  margin: 0;
}

.inv-preview-error {
  margin: 0;
  padding: 0.55rem 0.8rem;
  background: #FDECEC;
  border: 1px solid #F3C4C0;
  border-radius: var(--radius-sm);
  color: #A32020;
  font-size: 0.85rem;
  line-height: 1.6;
}

/* Bulk: the list of what will be issued, with live results. */
.inv-preview-list {
  margin-block-start: 1.1rem;
}

.inv-preview-table {
  width: 100%;
  font-size: 0.82rem;
}

.inv-preview-table td {
  vertical-align: top;
}

.inv-preview-item--issued td { background: #F3FBF6; }
.inv-preview-item--failed td { background: #FDECEC; }
.inv-preview-item--duplicate td,
.inv-preview-item--in_progress td,
.inv-preview-item--not_invoiceable td,
.inv-preview-item--future_deposit td { background: #FDF6E7; }
/* Never tried (server budget): plain, so it does not read as a failure. */
.inv-preview-item--not_attempted td { background: #F7F9FC; }

.inv-outcome {
  display: inline-block;
  margin-inline-end: 0.5rem;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  background: #EEF0F4;
  color: #6E7180;
}

.inv-outcome--issued { background: #E7F6ED; color: #1B7F4C; }
.inv-outcome--failed { background: #FDECEC; color: #A32020; }
.inv-outcome--duplicate,
.inv-outcome--not_invoiceable,
.inv-outcome--future_deposit { background: #FDF3E3; color: #8A5A12; }
.inv-outcome--in_progress { background: #EAF2FD; color: #0B5CC4; }
.inv-outcome--not_attempted {
  background: #fff;
  color: #6E7180;
  box-shadow: inset 0 0 0 1px #cfd6e2;
}

.inv-preview-item-error {
  display: block;
  margin-block-start: 0.15rem;
  font-size: 0.74rem;
  color: #A32020;
  white-space: normal;
}

.inv-preview-pending {
  font-size: 0.76rem;
  color: #8E8F9E;
}

.inv-preview-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 0.7rem 0 0;
  font-size: 0.86rem;
  color: #191A23;
}

/* Credit note: the linked-document picker. */
.inv-credit-targets {
  margin: 0;
  padding: 0.6rem 0.8rem;
  border: 1px solid #e6ebf2;
  border-radius: 10px;
  background: #F7F9FC;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.inv-credit-legend {
  padding-inline: 0.3rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: #5A5B6A;
}

.inv-credit-target {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.86rem;
  cursor: pointer;
}

.inv-credit-target input {
  margin-block-start: 0.25rem;
  flex: 0 0 auto;
}

.inv-credit-target-text {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.2rem 0.5rem;
}

.inv-credit-target-number {
  font-weight: 600;
  color: #191A23;
}

.inv-credit-target-meta {
  flex: 1 1 100%;
  font-size: 0.74rem;
  color: #8E8F9E;
}

.inv-credit-target--credited .inv-credit-target-number,
.inv-credit-target--cancelled .inv-credit-target-number {
  color: #8E8F9E;
  text-decoration: line-through;
}

/* Cannot be ticked (already credited / cancelled): dimmed, and the reason
   chip beside the number says which. */
.inv-credit-target--blocked {
  cursor: not-allowed;
  opacity: 0.7;
}

.inv-credit-target--chosen .inv-credit-target-number {
  color: #0B5CC4;
}

/* ── "סימון כהונפקה": the Morning document picker ──
   Reuses the credit note's target list wholesale (.inv-credit-target*): the two
   are the same object on the screen - a radio list of Morning documents where
   some rows cannot be ticked and say why. Only what differs lives here. */

.inv-mark {
  width: 720px;
}

/* Free text over the loaded rows, and the window that decides which rows those
   are. The text box takes the slack; the two dates keep their natural size. */
.inv-mark-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 0.8rem;
  margin-bottom: 0.6rem;
}

.inv-mark-filters .form-group {
  margin: 0;
}

.inv-mark-q {
  flex: 1 1 16rem;
  min-width: 0;
}

.inv-mark-date {
  flex: 0 0 auto;
}

/* Long lists scroll INSIDE the list rather than growing the modal past the
   viewport, which would push the confirm button off the bottom of the screen. */
.inv-mark-list {
  max-height: 20rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin-bottom: 0.9rem;
}

.inv-mark-doc {
  padding-block: 0.15rem;
}

/* The amount agrees with what is being claimed - the strongest signal on the
   row, so it is the only green thing in the list. */
.inv-mark-fit {
  background: #E9F7EF;
  color: #1B6B3A;
}

/* Already recorded against a payment of ours, which is why the row is dead. */
.inv-mark-taken {
  background: #FDECEC;
  color: #A32020;
}

.inv-mark-truncated,
.inv-mark-warning {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin: 0 0 0.8rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  font-size: 0.82rem;
  line-height: 1.6;
  background: #FDF3E3;
  border: 1px solid #EDD9A3;
  color: #8A5A12;
}

.inv-mark-truncated > i,
.inv-mark-warning > i {
  margin-block-start: 0.15rem;
}

/* The typing door: present, closed, and visibly the fallback. */
.inv-mark-manual {
  margin-top: 0.9rem;
  padding-top: 0.7rem;
  border-top: 1px solid #e6ebf2;
}

.inv-mark-manual > summary {
  cursor: pointer;
  font-size: 0.84rem;
  color: #5A5B6A;
}

.inv-mark-manual-note {
  margin: 0.5rem 0 0.8rem;
  font-size: 0.78rem;
  line-height: 1.6;
  color: #8E8F9E;
}

/* The running sum of what is linked, against the refund. */
.inv-credit-sum {
  margin: 0;
  font-size: 0.82rem;
  color: #5A5B6A;
  font-variant-numeric: tabular-nums;
}

.inv-credit-sum--over {
  color: #8A5A12;
}

.inv-credit-state {
  margin: 0;
  font-size: 0.82rem;
  color: #8E8F9E;
}

.inv-credit-state--error {
  color: #A32020;
}

.inv-credit-linktype {
  margin: 0;
  font-size: 0.86rem;
  color: #191A23;
}

@media (max-width: 1024px) {
  .inv-strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .inv-preview-grid,
  .inv-preview--bulk .inv-preview-grid {
    grid-template-columns: 1fr;
  }

  /* One column: the page keeps its height budget (so the whole sheet still
     fits) but may use the full width of a narrow modal. `width: auto` would
     leave the iframe's percentage width resolving against a shrink-to-fit
     box, which lands on the 300px intrinsic default. */
  .inv-preview {
    width: min(96vw, calc(var(--inv-pdf-w) + 3rem));
  }

  .inv-preview--bulk {
    width: min(96vw, 60rem);
  }

  /* Selection bar: fixed to the bottom, the leads bar's contract. 1018 is
     the modal rung on purpose: the tab bar is 1015 and LATER in the DOM, so
     at 1015 it would paint over this bar; a modal overlay is also 1018 and
     later still, so it keeps winning. Under 767px the tab bar is hidden
     outright while a selection is up (see the 767px block below). */
  .inv-bulk-bar {
    position: fixed;
    inset-inline: 0;
    inset-block-start: auto;
    inset-block-end: 0;
    z-index: 1018;
    margin: 0;
    border-radius: 0;
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    padding: 0.6rem 0.85rem calc(0.6rem + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -8px 28px rgba(0, 60, 130, 0.22);
  }

  .inv-bulk-bar .btn {
    flex: 0 0 auto;
    min-height: 44px;
  }

  .inv-bulk-bar .reg-bulk-count {
    flex: 0 0 auto;
  }

  .inv-bulk-bar .reg-bulk-spacer {
    margin-inline: 0;
  }

  /* Clear the fixed bar so the last card is never under it. */
  .inv-panel--bulk,
  .dep-page--bulk {
    padding-block-end: 5.5rem;
  }

  /* The installments table folds to cards, like every other table here. */
  .inv-it-wrap {
    overflow-x: visible;
  }

  .inv-it,
  .inv-it--compact .inv-it {
    display: block;
    min-width: 0;
    background: transparent;
    border: none;
    box-shadow: none;
  }

  .inv-it thead {
    display: none;
  }

  .inv-it tbody {
    display: block;
    width: 100%;
  }

  .inv-it tbody tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.2rem 0.7rem;
    width: 100%;
    margin-block-end: 0.7rem;
    padding: 0.7rem 0.9rem 0.6rem;
    background: #fff;
    border: 1px solid #e6ebf2;
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(0, 60, 130, 0.05);
  }

  .inv-it tbody tr.inv-it-row--deposited_uninvoiced {
    background: #FFF7F5;
    border-color: #F3C4C0;
  }

  .inv-it tbody tr.inv-it-row--selected {
    background: #EAF2FD;
    border-color: #B7D3F5;
  }

  .inv-it tbody tr:hover td,
  .inv-it tbody tr td {
    background: transparent;
  }

  .inv-it td {
    white-space: normal;
    border: none;
    padding: 0;
  }

  .inv-it td.inv-it-td-check {
    order: 0;
    width: auto;
    flex: 0 0 auto;
  }

  .inv-it td.inv-it-td-person {
    order: 1;
    flex: 1 1 auto;
    font-size: 0.95rem;
  }

  .inv-it td[data-label] {
    order: 3;
    flex: 1 1 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.6rem;
    padding-block: 0.3rem;
    border-block-start: 1px solid #f1f4f8;
    max-width: none;
  }

  .inv-it td[data-label]:empty {
    display: none;
  }

  .inv-it td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 7rem;
    color: #8a93a3;
    font-weight: 600;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    line-height: 1.7;
  }

  .inv-it td.inv-it-col-actions {
    order: 4;
    width: auto;
    flex: 1 1 100%;
    padding-block-start: 0.5rem;
    border-block-start: 1px solid #f1f4f8;
  }

  .inv-it td.inv-it-col-actions:not(:has(button)) {
    display: none;
  }

  .inv-it td.inv-it-empty {
    flex: 1 1 100%;
  }

  .inv-it .btn,
  .inv-it .btn-icon {
    min-height: 44px;
    min-width: 44px;
  }

  .inv-it-doc-btn {
    width: 44px;
    height: 44px;
  }
}

@media (max-width: 767px) {
  .inv-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .inv-it td[data-label]::before {
    flex: 0 0 5.5rem;
  }

  /* Selection mode owns the bottom edge (the Material selection-mode
     convention, the leads page's contract in admin.css): while the bulk
     bar is up on the payments tab or the deposits tab, the nav tab bar
     yields, so two fixed bars never stack on a 390px screen. */
  .admin-layout:has(.inv-panel--bulk) .adm-tabbar,
  .admin-layout:has(.dep-page--bulk) .adm-tabbar {
    display: none;
  }

  /* admin.css gives every modal `100dvh` at this width for one reason it spells
     out: `100vh` overshoots the VISIBLE viewport by the browser-chrome delta and
     hides the footer buttons. `.inv-preview` sets its own `max-height: 94vh`
     (the desktop sizing this modal is built around) at equal specificity from a
     later stylesheet, so it was winning here and re-opening that exact bug: on a
     390x844 iPhone with the toolbars up, 94vh is 793px inside a 745px viewport,
     and the overlay centres it with no scroll of its own - the whole footer, so
     Approve AND Cancel, lands off the bottom edge with no way to reach it.
     Match the panel-wide rule on a phone; desktop keeps 94vh untouched. */
  .inv-preview {
    max-height: 100vh;
    max-height: 100dvh;
  }

  /* And clear the home indicator, which the centring gap alone does not. */
  .inv-preview .modal-footer {
    padding-block-end: calc(0.75rem + env(safe-area-inset-bottom, 0px));
  }
}

/* ── The payments table (one row per ledger payment) ── */

.inv-toolbar {
  align-items: center;
}

.inv-synced {
  font-size: 0.76rem;
  color: #8E8F9E;
  font-variant-numeric: tabular-nums;
}

/* The sync ran out of server budget: one line, never a blocker. */
.inv-sync-note {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.76rem;
  color: #8A5A12;
}

.inv-select-toggle--on {
  background: #0f172a;
  color: #fff;
  border-color: #0f172a;
}

.inv-invoice-to-select {
  min-width: 10rem;
}

.inv-payments {
  min-width: 1240px;
}

.inv-th-expand,
.inv-td-expand {
  width: 2.2rem;
}

.inv-th-check,
.inv-td-check {
  width: 2rem;
}

.inv-td-installments {
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.inv-summary-chip {
  display: inline-block;
  padding: 0.14rem 0.55rem;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  background: #EEF0F4;
  color: #6E7180;
}

.inv-summary-chip--done { background: #E7F6ED; color: #1B7F4C; }
.inv-summary-chip--partial { background: #FDF3E3; color: #8A5A12; }
.inv-summary-chip--none { background: #EEF0F4; color: #6E7180; }
.inv-summary-chip--refund_uncredited { background: #FDF3E3; color: #8A5A12; box-shadow: inset 0 0 0 1px #EDD9A3; }
.inv-summary-chip--refund_credited { background: #F1ECFD; color: #5B3BC4; }

/* The row tint follows the loudest slot: money in the bank with no
   document.

   RAISED 2026-09-06 (owner). It was #FFF7F5 - about two per cent of red
   over white - which on a laptop screen in daylight was not tellable
   apart from an ordinary row, so the one state this whole table exists
   to surface was the one nobody could see without reading the chip on
   every line. It is now a real wash plus a solid bar down the row's
   start edge, so a block of work reads as a block before anything on it
   is read at all. The `לטיפול` chip is still the loudest single mark;
   this is the row saying "me" from across the screen.

   The bar goes on the FIRST CELL and not on the `<tr>`: under
   `border-collapse: collapse` a border declared on a table row is not
   painted. `inline-start` rather than `right` so the admin's RTL is the
   only thing deciding which edge it lands on. */
.inv-payment--deposited_uninvoiced td {
  background: #FDE7E3;
}

/* AND IT HAS TO SURVIVE THE POINTER. `.admin-table tr:hover td` in admin.css
   is (0,2,2) and paints #f8f9ff, which outranks the (0,1,1) rule above and
   wiped the wash off whichever row the reader's mouse happened to be over -
   i.e. precisely the row they were about to act on. Restated at (0,2,2) with
   its own slightly deeper tint, so hovering still reads as hovering. */
.inv-table tbody tr.inv-payment--deposited_uninvoiced:hover td {
  background: #FBD9D3;
}

.inv-payment--deposited_uninvoiced td:first-child {
  border-inline-start: 3px solid #B3261E;
}

.inv-payment--refund_uncredited td {
  background: #FFFBF2;
}

.inv-payment--open td {
  border-block-end-color: transparent;
}

.inv-row-detail > td {
  padding: 0;
  background: #f8fafc;
}

.inv-detail {
  padding: 0.6rem 0.9rem 0.9rem;
  border-top: 1px solid #e2e8f0;
}

@media (max-width: 1024px) {
  /* `.inv-payments` sets a desktop min-width AFTER the fold block above
     reset `.inv-table` to 0 (same specificity, later wins), which kept the
     folded cards 1240px wide and the expander chevron off a phone screen.
     Re-reset it here, after that declaration. */
  .inv-payments {
    min-width: 0;
  }

  .inv-table td.inv-td-check {
    order: 0;
    flex: 0 0 auto;
  }

  .inv-table td.inv-td-expand {
    order: 1;
    width: auto;
    flex: 0 0 auto;
    margin-inline-start: auto;
  }

  /* The expander is a full-width block under its card. */
  .inv-table tr.inv-row-detail {
    display: block;
    padding: 0.5rem 0.6rem;
    margin-block-start: -0.6rem;
  }

  .inv-table tr.inv-row-detail > td {
    display: block;
    width: 100%;
  }

  .inv-detail {
    padding: 0.4rem 0 0;
    border-top: none;
  }
}

/* The deposits report's plain yes/no chip, beside the phase chip. */
.inv-invoiced {
  display: inline-block;
  padding: 0.14rem 0.5rem;
  border-radius: 6px;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
  letter-spacing: 0.01em;
}

.inv-invoiced--yes {
  background: #1B7F4C;
  color: #fff;
}

.inv-invoiced--no {
  background: #fff;
  color: #B3261E;
  box-shadow: inset 0 0 0 1.5px #B3261E;
}
