/* ══════════════════════════════════════════════════════════
   /admin/card-payments - credit-card transactions read live
   from Telepay.

   Hebrew RTL island: .admin-main is pinned direction: ltr for
   the English admin pages, so this page root re-establishes
   RTL for itself only, exactly like .enr-page and .ct-page.
   Shared chrome (.admin-table, .reg-date-pill, .reg-detail,
   .btn, .empty-state, .toast) 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. No brand gradient on any weight above 400.
   ══════════════════════════════════════════════════════════ */

.cpay-page {
    direction: rtl;
    text-align: right;
}

/* ── Search field ──
   admin.css styles a 220px LTR box (.admin-search input, :439) and positions
   its icon and clear button physically. Three things went wrong here at once,
   all measured on screen: the input kept its 220px while .cpay-search grew to
   480px, so the clear X floated ~244px away from the field on bare page
   background; the input carried NO admin field styling at all (the markup was
   missing the .form-input class every other admin search box has), so it
   rendered as the browser's own 20px control with a 2px inset border and square
   corners beside a 39px rounded date-range trigger; and its 13.3px default font
   sits under iOS Safari's 16px focus-zoom floor.

   Scoped to .cpay-search rather than .admin-search so these win over the base
   width AND over both of admin.css's responsive variants (180px at <=1024px,
   100% at <=767px) without !important.

   TWO boxes now, and the second one was ADDED TO THESE SELECTOR LISTS rather
   than given a parallel rule of its own: the refund modal's sale search,
   .cpay-refund-search. It shipped carrying .admin-search alone and reproduced
   every defect above - measured at 1440px, a 220px input inside a 712px column
   with the magnifier stranded ~470px from it, the clear X mirrored to the start
   of the Hebrew line, a native 2px border at radius 0, 13.33px text under the
   iOS focus-zoom floor, and Chromium drawing its own cancel button beside ours.
   Below 767px it self-corrected, so it was broken on desktop and tablet only.
   The touch floors in the <=1024px block carry the same pair. A third box goes
   on these lists too. */
.cpay-page .cpay-search .fa-search,
.cpay-page .cpay-refund-search .fa-search {
    right: 0.75rem;
    left: auto;
    color: #8E8F9E;
}

.cpay-page .cpay-search input,
.cpay-page .cpay-refund-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;
}

.cpay-page .cpay-search input::placeholder,
.cpay-page .cpay-refund-search input::placeholder {
    color: #8E8F9E;
    opacity: 1;
}

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

/* The same ring the date-range trigger uses when open, so the two controls
   standing side by side focus identically. */
.cpay-page .cpay-search input:focus,
.cpay-page .cpay-refund-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. */
.cpay-page .cpay-search input::-webkit-search-cancel-button,
.cpay-page .cpay-search input::-webkit-search-decoration,
.cpay-page .cpay-refund-search input::-webkit-search-cancel-button,
.cpay-page .cpay-refund-search input::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
}

.cpay-page .cpay-search .search-clear,
.cpay-page .cpay-refund-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;
}

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

/* Embedded as a tab of /admin/payments there is no <h1> here, so the header row
   is just the subtitle and the toolbar. It cannot reuse .admin-page-header:
   that class carries its own responsive rules in admin.css which do not reach a
   new class name, and the 1.5rem bottom margin is too much air under a tab
   strip. */
.cpay-head--embedded {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 0.9rem;
}

.cpay-head--embedded .cpay-subtitle {
    margin-top: 0;
}

@media (max-width: 1024px) {
    .cpay-head--embedded {
        flex-direction: column;
        align-items: stretch;
    }
}

.cpay-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ── Header ── */

.cpay-heading {
    min-width: 0;
}

.cpay-subtitle {
    margin: 0.3rem 0 0;
    font-size: 0.84rem;
    line-height: 1.5;
    color: #5A5B6A;
    max-width: 62ch;
}

.cpay-updated {
    font-size: 0.78rem;
    color: #8E8F9E;
    white-space: nowrap;
}

/* ── Filter bar ── */

.cpay-filters {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.cpay-search {
    flex: 1 1 22rem;
    min-width: 14rem;
    max-width: 30rem;
}

.cpay-clear {
    white-space: nowrap;
}

.cpay-pills {
    margin-bottom: 0.9rem;
}

/* ── KPI band ── */

.cpay-kpis {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-bottom: 0.6rem;
}

.cpay-kpi {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.6rem 0.95rem;
    background: #fff;
    border: 1px solid #e6ebf2;
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(0, 60, 130, 0.05);
    min-width: 8.5rem;
}

/* Every tile explains which rows it counts - the tooltips are what stop
   staff subtracting two tiles that count different things. */
.cpay-kpi[title] {
    cursor: help;
}

.cpay-kpi-value {
    font-size: 1.16rem;
    font-weight: 600;
    line-height: 1.2;
    /* Solid brand ink, never the gradient: the gradient is forbidden above
       weight 400 and muddies on numerals. */
    color: #191A23;
    white-space: nowrap;
}

.cpay-kpi-label {
    font-size: 0.72rem;
    color: #8E8F9E;
    white-space: nowrap;
}

.cpay-kpi--money .cpay-kpi-value {
    color: #1B7F4C;
}

.cpay-kpi--warn .cpay-kpi-value {
    color: #C4551A;
}

.cpay-kpi--muted .cpay-kpi-value {
    color: #8E8F9E;
}

.cpay-kpi--refund .cpay-kpi-value {
    color: #8E8F9E;
}

/* The forecast pair. A colour of its own, and deliberately NOT the green the
   collected tile uses: green on this strip means money that has already been
   taken, and a figure that has not arrived yet must not borrow it. Indigo is
   the panel's "expected / scheduled" ink. */
.cpay-kpi--forecast .cpay-kpi-value {
    color: #3B4CCA;
}

/* The empty forecast prints a dash, which is a state and not a figure. */
.cpay-kpi-value--quiet {
    color: #8E8F9E;
}

/* The line under the label: the deposit date on one tile, how many dates the
   total covers on the other. It sits BELOW the label rather than above it
   because the label is what names the tile, and a date floating above its own
   name reads as a second value. Same colour as the label, one notch smaller,
   so the tile still has exactly one figure in it. */
.cpay-kpi-sub {
    font-size: 0.68rem;
    color: #8E8F9E;
    white-space: nowrap;
}

/* The scope marker on the two forecast tiles: they are the only ones on this
   strip that do NOT follow the filters, and a figure that stays put while the
   table shrinks reads as a bug without it.

   It is a tinted chip rather than a fourth grey line because the tile already
   ends in two muted lines and a third would be mush - and it sits LAST, pushed
   to the bottom, so every tile on the strip still starts with its figure on the
   same baseline. `align-self` keeps the chip its own width; in RTL flex-start is
   the right-hand edge, which is where the label above it starts. */
.cpay-kpi-scope {
    align-self: flex-start;
    margin-top: auto;
    padding: 0.05rem 0.4rem;
    border-radius: 999px;
    background: #EEF0FD;
    color: #3B4CCA;
    font-size: 0.62rem;
    line-height: 1.6;
    white-space: nowrap;
}

/* The band's footnote (.exvat-legend, admin-money.css). It sits between the
   tiles and the caution paragraph rather than in the page header, because it
   explains the bare `(1,695 ₪)` printed under every figure on the screen and a
   legend that scrolls away from its numbers stops working. Only the margins
   are local - the type and colour are the shared class's. */
.cpay-exvat-legend {
    margin: 0 0 0.7rem;
    max-width: 84ch;
}

/* The dimming of a row that took no money reaches its ex-VAT figure too. The
   shared class sets its own colour, which would otherwise leave a crisp
   qualifier under a struck-through amount, reading as though the parenthetical
   somehow survived the cancellation. */
.cpay-row--void .cpay-td-amount .exvat {
    color: #8E8F9E;
}

.cpay-caution {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    margin: 0 0 0.9rem;
    font-size: 0.78rem;
    line-height: 1.5;
    color: #6E7180;
    max-width: 84ch;
}

.cpay-caution i {
    margin-top: 0.2rem;
    color: #8E8F9E;
    flex: 0 0 auto;
}

/* ── Stale feed ── */

.cpay-stale-banner {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.55rem 0.85rem;
    margin-bottom: 0.85rem;
    background: #FFF6E8;
    border: 1px solid #F2D9AE;
    border-radius: 10px;
    font-size: 0.82rem;
    color: #8A5A12;
}

.cpay-stale-banner span {
    flex: 1 1 20rem;
    line-height: 1.5;
}

/* Deliberately outside the dimmed region - it is what explains the dimming. */
.cpay-stale-retry {
    flex: 0 0 auto;
}

/* Everything rendered from the last payload dims together - dimming a
   subset is worse than dimming nothing. */
.cpay-stale {
    opacity: 0.55;
    transition: opacity 0.15s ease;
}

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

/* Telepay's reporting call runs 3.5-30s, so this state is on screen long enough
   to need to look alive. The elapsed counter and the patience line appear at 3s
   and 6s, after the fast responses have already landed. */
.cpay-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
    line-height: 1.6;
}

.cpay-loading-line {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
}

.cpay-loading-hint {
    margin: 0;
    max-width: 48ch;
    font-size: 0.82rem;
    color: #8E8F9E;
}

/* The address to quote to Telepay. Monospaced because it gets copied out by
   hand into a support request, and a misread digit costs a round trip. */
.cpay-blocked-ip {
    margin: 0;
    font-size: 0.85rem;
    color: var(--admin-text-muted, #6b7280);
}

.cpay-blocked-ip bdi {
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    user-select: all;
}

/* Inside the stale banner the address takes its own line: the banner is a flex
   row, and this is a value to be copied out, not part of the sentence. Beats
   `.cpay-stale-banner span` on specificity, which is what puts it there. */
.cpay-stale-banner .cpay-stale-banner-ip {
    flex: 1 1 100%;
    color: inherit;
}

/* Where to read the same numbers while this screen is blocked. */
.cpay-blocked-alt {
    margin: 0;
    font-size: 0.9rem;
}

.cpay-blocked-alt .fas {
    font-size: 0.75em;
    margin-inline-start: 0.25rem;
}

/* ── Table ── */

/* Horizontal scroll lives here, never on the page body. Contained so a
   swipe that reaches the table's edge does not start dragging the page. */
.cpay-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
}

.cpay-table {
    min-width: 1160px;
}

.cpay-table th,
.cpay-table td {
    white-space: nowrap;
}

.cpay-th-expand,
.cpay-td-expand {
    width: 2.4rem;
    padding-inline: 0.4rem;
}

.cpay-td-date {
    font-variant-numeric: tabular-nums;
    color: #47505c;
}

.cpay-td-amount {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: #191A23;
}

.cpay-td-refund {
    font-variant-numeric: tabular-nums;
    color: #C4551A;
}

.cpay-td-reason {
    max-width: 16rem;
    overflow: hidden;
    text-overflow: ellipsis;
    color: #C4551A;
    font-size: 0.82rem;
}

.cpay-td-email {
    max-width: 15rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The buyer's name doubles as the way into their person card. It has to LOOK
   like the plain name it wraps - the same call the all-sales table makes for
   its own first column - because a blue underlined name in every row would
   turn the column into a wall of links. The focus ring is the browser default,
   deliberately left alone: it is the only thing that shows a keyboard user
   where they are. */
.cpay-person-link {
    color: inherit;
    text-decoration: none;
}

.cpay-person-link:hover,
.cpay-person-link:focus-visible {
    text-decoration: underline;
}

/* Marks a name Telepay never received, filled in from the sale the charge paid
   for. Muted and small on purpose: it qualifies the value beside it, it is not
   a second value. The sentence itself is the title attribute, and the detail
   panel prints it in full. */
.cpay-ledger-hint {
    margin-inline-start: 0.32rem;
    color: #8E8F9E;
    font-size: 0.72rem;
    cursor: help;
}

/* The same annotation, at sentence length, inside the expanded row. */
.cpay-answer-note {
    color: #5A5B6A;
    font-size: 0.78rem;
    line-height: 1.45;
}

/* A row that took no money is dimmed so the eye can skip it, but never
   hidden - it is the record of an attempt. */
.cpay-row--void .cpay-td-amount {
    font-weight: 400;
    color: #8E8F9E;
    text-decoration: line-through;
    text-decoration-color: rgba(142, 143, 158, 0.6);
}

/* ── Status badge ── */

.cpay-badge {
    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;
}

.cpay-badge--deposited {
    background: #E7F6ED;
    color: #1B7F4C;
}

/* Cleared is money in, same as deposited, so it stays in the green family -
   lighter, because the bank transfer has not happened yet. */
.cpay-badge--cleared {
    background: #EAF7F0;
    color: #2F8C63;
}

.cpay-badge--failed {
    background: #FDECE4;
    color: #C4551A;
}

.cpay-badge--cancelled {
    background: #EEF0F4;
    color: #6E7180;
}

.cpay-badge--other {
    background: #EAF2FD;
    color: #0B5CC4;
}

/* Sits BESIDE the status badge, never instead of it: the status word is
   Telepay's own and is reproduced verbatim everywhere on this screen, while
   this chip is our reading of which direction the money went. The two-badge
   cell is the only one in the table, so it needs the gap. */
.cpay-td-status .cpay-badge + .cpay-badge {
    margin-inline-start: 0.3rem;
}

/* Money leaving. Deliberately NOT the failed/red family - a refund is not an
   error - and not the green one either. The same warm orange the "הוחזר"
   column already uses for refunded money, so the two read as one idea. */
.cpay-badge--refund {
    background: #FBEFE6;
    color: #B4500F;
}

/* A refund's amount is printed with our own minus sign, so it gets the colour
   that goes with it. Weight stays at the table's 600 - this is a real figure,
   unlike a void row's struck-through attempt. */
.cpay-row--refund .cpay-td-amount {
    color: #B4500F;
}

/* A DECLINED refund is both: no money moved, so the void rule strikes it
   through, and the strike-through's grey has to win over the refund colour or
   the row claims money went back when none did. */
.cpay-row--refund.cpay-row--void .cpay-td-amount {
    color: #8E8F9E;
}

/* ── Expanded detail ── */

.cpay-detail {
    gap: 1.4rem 2rem;
}

.cpay-detail .reg-answer-q {
    white-space: nowrap;
}

/* ── Pagination ── */

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

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

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

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

.cpay-page-size-select {
    padding: 0.2rem 0.45rem;
    border: 1px solid #dfe4ec;
    border-radius: 8px;
    background: #fff;
    font-size: 0.8rem;
    color: #47505c;
}

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

   The 12-column desktop table cannot fit below 1024px, and the
   generic .admin-table fixed-layout rule in admin.css crushes
   every column into an unreadable overlap. Each cell carries a
   data-label, printed as its own caption.
   ══════════════════════════════════════════════════════════ */

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

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

    .cpay-table thead {
        display: none;
    }

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

    .cpay-table tbody tr {
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 0.2rem 0.7rem;
        width: 100%;
        margin-bottom: 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);
    }

    .cpay-table tbody tr:hover td {
        background: transparent;
    }

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

    /* The four identity cells lead the card, unlabelled. */
    .cpay-table td.cpay-td-expand {
        order: 1;
        width: auto;
        margin-inline-start: auto;
    }

    .cpay-table td.cpay-td-date {
        order: 0;
        font-size: 0.8rem;
        color: #8E8F9E;
        flex: 1 1 auto;
    }

    .cpay-table td.cpay-td-amount {
        order: 2;
        flex: 0 0 100%;
        font-size: 1.05rem;
    }

    .cpay-table td.cpay-td-status {
        order: 3;
    }

    .cpay-table td.cpay-td-reason {
        order: 4;
        flex: 1 1 100%;
        max-width: none;
    }

    /* The desktop table clips long addresses to an ellipsis because the row
       must stay one line. A card has no such constraint, so the cap is
       released and the address wraps instead of being silently truncated. */
    .cpay-table td.cpay-td-email {
        max-width: none;
        overflow: visible;
        text-overflow: clip;
        word-break: break-all;
    }

    /* Everything else stacks as labelled rows. */
    .cpay-table td[data-label] {
        order: 5;
        flex: 1 1 100%;
        display: flex;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 0.15rem 0.6rem;
        padding: 0.34rem 0;
        border-top: 1px solid #f1f4f8;
    }

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

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

    /* The detail row is a full-width block under its card. */
    .cpay-table tr.reg-row-detail {
        display: block;
        padding: 0.85rem 1rem;
        margin-top: -0.6rem;
    }

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

    .cpay-detail {
        gap: 1rem;
    }

    /* ── Touch floors (admin mobile revamp) ──
       44px targets and 16px input text across the whole sub-1025 band, not
       only phones. 16px exactly on the input: anything smaller makes iOS
       Safari zoom the whole page on focus, and the page never zooms back
       out. 2.75rem = 44px. */
    .cpay-page .cpay-search input,
    .cpay-page .cpay-refund-search input {
        min-height: 2.75rem;
        padding-left: 3.3rem;
        font-size: 16px;
    }

    .cpay-page .cpay-search .search-clear,
    .cpay-page .cpay-refund-search .search-clear {
        width: 2.75rem;
        height: 2.75rem;
        left: 0.25rem;
    }

    .cpay-page .btn,
    .cpay-page .btn-icon {
        min-height: 44px;
        min-width: 44px;
    }

    .cpay-page .reg-date-pill {
        min-height: 44px;
    }

    .cpay-page .cpay-page-size-select {
        font-size: 16px;
        min-height: 44px;
    }
}

@media (max-width: 767px) {
    .cpay-filters {
        gap: 0.5rem;
    }

    .cpay-search {
        flex: 1 1 100%;
        max-width: none;
    }

    /* The search input's 16px/44px floors moved to the 1024px block above -
       the whole sub-1025 band gets them, not only phones. */

    .cpay-kpi {
        flex: 1 1 8rem;
        min-width: 0;
        padding: 0.5rem 0.7rem;
    }

    .cpay-kpi-value {
        font-size: 1rem;
    }

    .cpay-pagination {
        gap: 0.5rem;
    }

    .cpay-pagination-mid {
        order: 3;
        flex: 1 1 100%;
        justify-content: space-between;
    }
}

/* ══════════════════════════════════════════════════════════
   Recording a refund.

   The one write on this screen. It does not move money: Telepay
   has no refund verb, so a person refunds in their backoffice
   and this records the fact against one of our sales. Every
   colour choice below follows from that - the action is a plain
   button, never a red one, because red would read as "undo the
   charge" on a control that undoes nothing.
   ══════════════════════════════════════════════════════════ */

.cpay-th-actions,
.cpay-td-actions {
    width: 1%;
    white-space: nowrap;
    text-align: start;
}

.cpay-refund-btn {
    gap: 0.35rem;
}

/* ── The modal ── */

.cpay-refund-modal .modal-body {
    /* The suggestion list can run long; the modal's own 85vh cap
       does the scrolling, so nothing here fixes a height. */
    display: block;
}

.cpay-refund-lede {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin: 0 0 1rem;
    padding: 0.7rem 0.85rem;
    background: #fff6ec;
    border: 1px solid #f2d3b0;
    border-radius: 8px;
    color: #7a4412;
    font-size: 0.86rem;
    line-height: 1.6;
}

.cpay-refund-lede i {
    margin-top: 0.2rem;
    flex: 0 0 auto;
}

.cpay-refund-charge {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.3rem 0.6rem;
    margin-bottom: 1rem;
    padding: 0.6rem 0.85rem;
    background: #f6f7fb;
    border: 1px solid #e0e3ea;
    border-radius: 8px;
    font-size: 0.85rem;
}

.cpay-refund-charge-label {
    color: #8a93a3;
    font-weight: 600;
    font-size: 0.72rem;
    letter-spacing: 0.04em;
}

.cpay-refund-charge-facts {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.3rem 0.5rem;
    color: #191A23;
    font-variant-numeric: tabular-nums;
}

.cpay-refund-sep {
    color: #b9c0cc;
}

.cpay-refund-note {
    margin: 0.35rem 0 0.6rem;
    color: #47505c;
    font-size: 0.84rem;
    line-height: 1.6;
}

.cpay-refund-warn {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin: 0.35rem 0 0.8rem;
    padding: 0.55rem 0.75rem;
    background: #fdf3f0;
    border: 1px solid #f0cec3;
    border-radius: 8px;
    color: #8a3a15;
    font-size: 0.83rem;
    line-height: 1.6;
}

/* The search box inside the modal. Narrower than the table's own
   search and always full width - it sits in a form column, not a
   toolbar. */
.cpay-refund-search {
    max-width: none;
    margin: 0.35rem 0 0.6rem;
}

/* Says the rows below were typed for, not compared. Quiet, because it
   is an explanation and not a warning: searching is a legitimate way
   to work, it just makes no claim about this charge. */
.cpay-refund-searchnote {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    padding: 0.5rem 0.7rem;
    background: #f6f7fb;
    border: 1px solid #e0e3ea;
    border-radius: 8px;
}

.cpay-refund-searchnote i {
    margin-top: 0.2rem;
    flex: 0 0 auto;
}

/* What keeps proof and typing apart. Proof gets its own heading above
   its own row, so the exact match can never read as the top of a list
   of things somebody searched for. */
.cpay-sug-group-title {
    display: block;
    margin: 0.7rem 0 0.35rem;
    color: #8a93a3;
    font-weight: 600;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
}

/* ── One candidate sale ── */

.cpay-sug {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    margin-bottom: 0.5rem;
    padding: 0.6rem 0.8rem;
    background: #fff;
    border: 1px solid #e0e3ea;
    border-radius: 10px;
    cursor: pointer;
}

.cpay-sug input {
    margin-top: 0.25rem;
    flex: 0 0 auto;
}

.cpay-sug--selected {
    border-color: #6935d8;
    box-shadow: 0 0 0 1px #6935d8 inset;
}

/* THE ONE ROW THAT IS EVIDENCE. `--proven` is the sale our own server named by
   the transaction id it stored when it placed the charge; every other row in
   the list is a resemblance or a thing somebody typed.

   It was bound in the template and defined nowhere, so an UNSELECTED proven row
   was pixel-identical to a guess - while `--found`, the tier that was never
   compared to this charge at all, did get a tint and a dashed border. It only
   looked right because the proven row is auto-selected; clicking anything else
   left proof with no distinction of its own.

   Deliberately quieter than `--selected` and in a different channel: selection
   is the purple ring, proof is a green start-edge rule and a faint wash, so a
   row can carry both at once and each still reads. The rule is on the START
   edge, which the RTL island puts on the right. */
.cpay-sug--proven {
    background: #f6fbf8;
    border-color: #cfe6d9;
    border-inline-start-width: 3px;
    border-inline-start-color: #2e8b57;
}

/* Proof beats a search hit where a row is somehow both, which is the one
   ordering these two tiers can disagree about. */
.cpay-sug--proven.cpay-sug--found {
    border-style: solid;
    background: #f6fbf8;
}

.cpay-sug-body {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}

.cpay-sug-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem 0.6rem;
    font-size: 0.92rem;
    color: #191A23;
}

.cpay-sug-cohort {
    color: #47505c;
    font-size: 0.82rem;
}

.cpay-sug-conf {
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.03em;
}

/* Proof and resemblance must not read alike. The proven match is
   the only one that gets a solid, confident chip; the two
   heuristic tiers stay deliberately quiet. */
.cpay-sug-conf--exact {
    background: #e7f6ec;
    border: 1px solid #b7e0c4;
    color: #1c6b39;
}

.cpay-sug-conf--likely {
    background: #f6f7fb;
    border: 1px solid #dfe3ea;
    color: #5c6472;
}

/* A row that makes no claim at all. Reachable when the server sends
   `none` with something other than `search` - it must read as "not
   ranked", never borrow the bottom rung of the ramp. */
.cpay-sug-conf--none {
    background: #eef1f6;
    border: 1px solid #d7dce4;
    color: #5c6472;
}

.cpay-sug-conf--possible {
    background: #f6f7fb;
    border: 1px dashed #cdd3dd;
    color: #7b828f;
}

/* The sale's own state, on every candidate. Live is a quiet reading;
   anything else is a mark, because attaching a refund to a dead sale
   is legitimate but must never happen unnoticed. */
.cpay-sug-status {
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.03em;
}

.cpay-sug-status--live {
    background: #f6f7fb;
    border: 1px solid #dfe3ea;
    color: #5c6472;
}

.cpay-sug-status--dead {
    background: #fdf3f0;
    border: 1px solid #e6b7a6;
    color: #8a3a15;
}

/* A searched row is a DIFFERENT KIND of row, not the weakest
   suggestion. So it gets a square, neutral tag rather than a pill on
   the confidence ramp, and the row itself is tinted away from the
   ranked ones instead of sitting at the bottom of them. */
.cpay-sug--found {
    background: #fbfcfe;
    border-style: dashed;
}

.cpay-sug-found-tag {
    padding: 0.05rem 0.45rem;
    border-radius: 4px;
    background: #eef1f6;
    border: 1px solid #d7dce4;
    color: #5c6472;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.03em;
}

.cpay-sug-why {
    color: #6c7480;
    font-size: 0.79rem;
    line-height: 1.5;
}

.cpay-sug-nums {
    color: #47505c;
    font-size: 0.79rem;
    font-variant-numeric: tabular-nums;
}

/* The "no matching sale" explanation. Deliberately quiet: it is a
   fact about this charge, not a failure the reader can act on here. */
.cpay-refund-nosale {
    padding: 0.55rem 0.75rem;
    background: #f6f7fb;
    border: 1px solid #e0e3ea;
    border-radius: 8px;
}

.cpay-refund-toggles {
    flex-direction: column;
    gap: 0.5rem;
}

.cpay-refund-toggles-note {
    margin: 0.15rem 0 0;
    color: #6c7480;
    font-size: 0.78rem;
    line-height: 1.5;
}

/* The contract control sits UNDER "cancel the sale" and belongs to it, so it
   is indented to say so - the same treatment `.per-refund-nested` gives the
   twin control on the person page. RTL island: the indent is on the start
   edge, which is the right one here. */
.cpay-refund-nested {
    margin-inline-start: 1.35rem;
}

/* Said once, above the table, when the feature switch is PROVEN down. Quiet
   and informational: nothing is broken and there is nothing to retry - the
   reader has to go and turn a setting on, or ask somebody who can. */
.cpay-refunds-off {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin: 0 0 1rem;
    padding: 0.6rem 0.85rem;
    background: #f6f7fb;
    border: 1px solid #e0e3ea;
    border-radius: 8px;
    color: #47505c;
    font-size: 0.85rem;
    line-height: 1.6;
}

.cpay-refunds-off i {
    margin-top: 0.2rem;
    flex: 0 0 auto;
}

/* The sentence takes the room and the button sits at the end of it, rather
   than the button wrapping onto a line of its own on a wide screen. */
.cpay-refunds-off span {
    flex: 1 1 20rem;
    min-width: 0;
}

/* Quiet, and beside the search box rather than in place of the rows. The
   whole point of this marker is that the candidate list does NOT unmount
   while somebody types. */
.cpay-refund-refreshing {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.4rem;
    color: #6c7480;
    font-size: 0.78rem;
}

/* A statement about OUR list, so it wears the same quiet treatment as the
   "these were not compared to the charge" note directly under it, not the
   warning colours - nothing has gone wrong. */
.cpay-refund-truncated {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    padding: 0.5rem 0.7rem;
    background: #f6f7fb;
    border: 1px solid #e0e3ea;
    border-radius: 8px;
}

.cpay-refund-truncated i {
    margin-top: 0.2rem;
    flex: 0 0 auto;
}

/* Inside the modal's failure box the address takes its own line: the box is a
   flex row, and this is a value to be copied out rather than part of the
   sentence it follows. */
.cpay-refund-warn .cpay-blocked-ip {
    flex: 1 1 100%;
    color: inherit;
    font-size: 0.79rem;
}

.cpay-refund-block {
    margin: 0.6rem 0 0;
    color: #8a3a15;
    font-size: 0.83rem;
    line-height: 1.6;
}

@media (max-width: 1024px) {
    /* The card layout prints each cell's own caption. The action
       cell keeps the labelled treatment so the button does not
       float loose under the amounts. */
    .cpay-table td.cpay-td-actions {
        width: auto;
        white-space: normal;
    }

    .cpay-refund-charge-facts {
        flex: 1 1 100%;
    }
}

/* ── The ledger installments pane (installment invoicing, D6b) ──
   Spans the whole detail grid: the installments table is wide, and the
   five fact columns above it are not. The table itself is the shared
   `.inv-it` kit from admin-invoices.css. */

.cpay-ledger {
    grid-column: 1 / -1;
}

.cpay-ledger-note {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0;
    font-size: 0.84rem;
    color: #6b7280;
}

.cpay-ledger-note--error {
    color: #A32020;
}

/* ── Telepay's own management system, at the foot of the screen ──
   It used to be a tab of its own on the host page. One link does not
   need a screen, and it belongs beside the table it is the alternative
   reading of: when our reporting call is refused, the panel higher up
   sends the reader to the same place in a sentence that only makes
   sense while the table is empty. This one is always there.

   Quiet on purpose - a bar, not a card. It sits under the pagination of
   a money table and must not compete with it for the eye. */

.cpay-backoffice {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem 1.25rem;
    margin-top: 1.75rem;
    padding: 1rem 1.15rem;
    background: #fff;
    border: 1px solid #eef0f6;
    border-radius: 12px;
}

.cpay-backoffice-text {
    min-width: 0;
}

.cpay-backoffice-title {
    margin: 0 0 0.2rem;
    font-size: 0.95rem;
    font-weight: 600;
    color: #191a23;
}

.cpay-backoffice-note {
    margin: 0;
    font-size: 0.82rem;
    line-height: 1.55;
    color: #5a5b6a;
}

.cpay-backoffice-btn {
    flex: 0 0 auto;
}

@media (max-width: 767px) {
    .cpay-backoffice {
        align-items: stretch;
        flex-direction: column;
    }

    .cpay-backoffice-btn {
        justify-content: center;
    }
}
