/* ===========================================================================
   table.css — data tables, and their responsive card fallback.
   ---------------------------------------------------------------------------
   Tables are where a trading product lives: positions, orders, deposits,
   withdrawals, markets, audit log. Requirements this file is built against:

   - Numeric columns must line up and not jitter as prices tick.
   - The header must stay visible while a long list scrolls.
   - On a phone, a 9-column table must remain usable without pinch-zoom.
   - A row action must be reachable by keyboard.

   Markup contract (src/View/ui.php → ui_table_open()):

     <div class="table-wrap">
       <table class="table">
         <caption class="sr-only">Open positions</caption>
         <thead><tr><th scope="col">…</th><th scope="col" class="num">…</th></tr></thead>
         <tbody>
           <tr>
             <td data-label="Market">…</td>
             <td data-label="Size" class="num">…</td>
           </tr>
         </tbody>
       </table>
     </div>

   data-label on every cell is what powers the phone card view below, so it is
   not optional — ui_table_row() emits it from the header definition.
   =========================================================================== */

.table-wrap {
    /* The horizontal scroll container. Also the focus scroller, so a keyboard
       user can pan a wide table with arrow keys once it is focused. */
    width: 100%;
    overflow-x: auto;
    overflow-y: visible;
    -webkit-overflow-scrolling: touch;
    /* Lets the sticky thead work: a scroll container is required. */
    position: relative;
}

/* A fixed-height scroller for long lists, with the header pinned. */
.table-wrap--scroll {
    max-height: 60vh;
    overflow-y: auto;
}

.table {
    width: 100%;
    /* auto (not fixed): financial columns have wildly different natural
       widths and fixed layout truncates symbols before it truncates
       whitespace. Individual widths are constrained per column below. */
    table-layout: auto;
    border-collapse: separate;   /* separate, so sticky headers keep borders */
    border-spacing: 0;
    font-size: var(--text-sm);
}

/* ---------------------------------------------------------------------------
   Header
   --------------------------------------------------------------------------- */
.table thead th {
    position: sticky;
    inset-block-start: 0;
    z-index: var(--z-sticky);
    padding: var(--pad-cell-y) var(--pad-cell-x);
    background: var(--surface-sunken);
    color: var(--text-muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-caps);
    white-space: nowrap;
    text-align: start;
    /* box-shadow rather than border-bottom: a sticky element's own border
       scrolls away in some engines, a shadow does not. */
    box-shadow: inset 0 -1px 0 var(--border);
}

.table thead th.num {
    text-align: end;
}

/* Sortable header. The whole cell is the button target. */
.table th[aria-sort] {
    cursor: pointer;
    user-select: none;
}

.table th[aria-sort]:hover {
    color: var(--text);
    background: var(--surface-hover);
}

.table th[aria-sort]::after {
    content: "";
    display: inline-block;
    width: 0;
    height: 0;
    margin-inline-start: var(--space-2);
    vertical-align: middle;
    border-inline: 4px solid transparent;
    /* Neutral state: a dimmed double marker would be noisier than nothing,
       so unsorted columns show a faint down caret only on hover. */
    opacity: 0;
    border-block-start: 5px solid currentColor;
    transition: opacity var(--duration-fast) var(--ease-out);
}

.table th[aria-sort]:hover::after {
    opacity: 0.4;
}

.table th[aria-sort="ascending"]::after {
    opacity: 1;
    border-block-start: 0;
    border-block-end: 5px solid var(--accent);
}

.table th[aria-sort="descending"]::after {
    opacity: 1;
    border-block-start: 5px solid var(--accent);
}

/* ---------------------------------------------------------------------------
   Body
   --------------------------------------------------------------------------- */
.table tbody td {
    padding: var(--pad-cell-y) var(--pad-cell-x);
    border-block-end: 1px solid var(--border-subtle);
    color: var(--text-secondary);
    vertical-align: middle;
}

.table tbody tr:last-child td {
    border-block-end: 0;
}

.table tbody tr {
    transition: background-color var(--duration-fast) var(--ease-out);
}

.table tbody tr:hover {
    background: var(--surface-hover);
}

/* The first column is the row's identity (symbol, id, date) and reads as
   primary text rather than secondary. */
.table tbody td:first-child {
    color: var(--text);
    font-weight: var(--weight-medium);
}

/* Numeric cells inherit mono/tabular/LTR from base.css via .num; this only
   handles alignment and weight. */
.table td.num {
    text-align: end;
    color: var(--text);
    white-space: nowrap;
}

/* Row states. A left accent bar rather than a full background tint, so the
   row's own directional colours stay readable. */
.table tbody tr.is-selected {
    background: var(--accent-dim);
}

.table tbody tr[data-state="pending"] td:first-child {
    box-shadow: inset 3px 0 0 var(--pending);
}

.table tbody tr[data-state="danger"] td:first-child {
    box-shadow: inset 3px 0 0 var(--danger);
}

/* A row for a record that exists but is switched off — an inactive strategy,
   a paused market. Dimmed rather than hidden, because the operator is often
   looking for exactly the one that is off. The marker border is deliberately
   absent: nothing needs attention here. */
.table tbody tr[data-state="muted"] td {
    color: var(--text-muted);
}

.table tbody tr[data-state="success"] td:first-child {
    box-shadow: inset 3px 0 0 var(--success);
}

[dir="rtl"] .table tbody tr[data-state] td:first-child {
    box-shadow: inset -3px 0 0 currentColor;
}

/* A clickable row. Still requires a real focusable control inside for
   keyboard users — this is affordance only. */
.table tbody tr.is-clickable {
    cursor: pointer;
}

/* Actions column: pinned to the inline end, never wraps, and shrinks to fit. */
.table td.table__actions,
.table th.table__actions {
    width: 1%;
    white-space: nowrap;
    text-align: end;
}

.table td.table__actions > * + * {
    margin-inline-start: var(--space-1);
}

/* ---------------------------------------------------------------------------
   Density variants
   --------------------------------------------------------------------------- */
.table--compact tbody td,
.table--compact thead th {
    padding-block: var(--space-2);
}

.table--roomy tbody td {
    padding-block: var(--space-4);
}

/* Zebra striping. Off by default (hairlines are enough and stripes fight the
   tick-flash animation); available where a table is very wide. */
.table--striped tbody tr:nth-child(even) {
    background: var(--surface-sunken);
}

.table--striped tbody tr:nth-child(even):hover {
    background: var(--surface-hover);
}

/* ---------------------------------------------------------------------------
   Footer / totals row
   --------------------------------------------------------------------------- */
.table tfoot td {
    padding: var(--pad-cell-y) var(--pad-cell-x);
    background: var(--surface-sunken);
    border-block-start: 1px solid var(--border);
    font-weight: var(--weight-bold);
    color: var(--text);
    position: sticky;
    inset-block-end: 0;
}

/* ---------------------------------------------------------------------------
   Toolbar above a table — search, filters, export.
   --------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   BULK BAR — appears once rows are selected, and says how many.

   Sits between the filters and the content rather than floating over it: a
   bar that overlaps the last row hides exactly the thing the operator is
   deciding about. role="region" with a label so a screen reader can jump to
   it once it appears.
   --------------------------------------------------------------------------- */
.bulk-bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    padding: var(--space-3) var(--pad-card);
    background: var(--accent-dim);
    border-block-end: 1px solid var(--border-subtle);
}

.bulk-bar[hidden] {
    display: none;
}

.bulk-bar__count {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--accent-text);
    font-variant-numeric: tabular-nums;
}

.bulk-bar__actions {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
}

.table-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-3);
    padding: var(--pad-card-sm) var(--pad-card);
    border-block-end: 1px solid var(--border-subtle);
}

.table-toolbar__search {
    flex: 1 1 200px;
    max-width: 320px;
}

.table-toolbar__end {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.table-count {
    font-size: var(--text-xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Pagination
   --------------------------------------------------------------------------- */
.pager {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--pad-card-sm) var(--pad-card);
    border-block-start: 1px solid var(--border-subtle);
    flex-wrap: wrap;
}

.pager__info {
    font-size: var(--text-xs);
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.pager__controls {
    margin-inline-start: auto;
    display: flex;
    align-items: center;
    gap: var(--space-1);
}

/* ===========================================================================
   RESPONSIVE: table → cards.
   ---------------------------------------------------------------------------
   Below the tablet breakpoint a data table becomes a stack of cards, one per
   row, with each cell labelled from its data-label. This is applied only to
   .table--cards, because some tables (a 3-column price list) are better left
   as a narrow table than converted.

   The <table> semantics are removed along with the visual table, which is the
   accepted trade-off: display:block on table elements drops the implicit
   grid semantics, so the caption plus per-cell labels carry the meaning
   instead. Tables that must keep row/column semantics on mobile use
   .table--scroll and pan horizontally.
   =========================================================================== */
@media (max-width: 768px) {
    .table--cards thead {
        /* clip, not display:none — display:none on a thead is announced as
           removed content by some screen readers even in card mode. */
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
    }

    .table--cards,
    .table--cards tbody,
    .table--cards tr,
    .table--cards td {
        display: block;
        width: auto;
    }

    .table--cards tbody tr {
        padding: var(--pad-card-sm);
        margin-block-end: var(--space-3);
        background: var(--surface-raised);
        border: 1px solid var(--border);
        border-radius: var(--radius-md);
    }

    .table--cards tbody tr:last-child {
        margin-block-end: 0;
    }

    .table--cards tbody td {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--space-4);
        padding: var(--space-2) 0;
        border-block-end: 1px solid var(--border-subtle);
        text-align: start;
    }

    .table--cards tbody td:last-child {
        border-block-end: 0;
        padding-block-end: 0;
    }

    /* The label, pulled from data-label. */
    .table--cards tbody td::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: var(--text-xs);
        font-weight: var(--weight-semibold);
        color: var(--text-muted);
        text-transform: uppercase;
        letter-spacing: var(--tracking-caps);
        /* The label is UI text and follows page direction; the value keeps
           its own direction from .num. It also keeps the UI face - inside a
           .num cell it inherited the monospace stack. */
        direction: inherit;
        font-family: var(--font-ui);
    }

    /* The identity cell becomes the card's title: full width, no label. */
    .table--cards tbody td:first-child {
        justify-content: flex-start;
        padding-block-start: 0;
        font-size: var(--text-md);
        font-weight: var(--weight-semibold);
    }

    .table--cards tbody td:first-child::before {
        display: none;
    }

    /* Numeric values keep end alignment, which in card view means "opposite
       the label". */
    .table--cards tbody td.num {
        text-align: end;
        /* .num makes the cell direction: ltr, and in card view the cell is the
           flex row holding label and value - so on an Arabic page every numeric
           row put its label on the left while the other rows had it on the
           right. The row takes the page direction back; plaintext still lays
           the figure itself out LTR, keeping "±4,800.00" and "10-03 18:21"
           in order. */
        direction: inherit;
        unicode-bidi: plaintext;
    }

    /* Actions get their own full-width row of buttons. */
    .table--cards tbody td.table__actions {
        display: flex;
        justify-content: stretch;
        gap: var(--space-2);
        padding-block-start: var(--space-3);
        width: 100%;
    }

    .table--cards tbody td.table__actions::before {
        display: none;
    }

    .table--cards tbody td.table__actions > * {
        flex: 1 1 auto;
        margin-inline-start: 0;
    }

    /* Row state markers move to the card's whole inline-start edge. */
    .table--cards tbody tr[data-state="pending"] { border-inline-start: 3px solid var(--pending); }
    .table--cards tbody tr[data-state="danger"] { border-inline-start: 3px solid var(--danger); }
    .table--cards tbody tr[data-state="success"] { border-inline-start: 3px solid var(--success); }

    .table--cards tbody tr[data-state] td:first-child {
        box-shadow: none;
    }

    .table--cards tfoot {
        display: block;
    }

    .table--cards tfoot td {
        display: flex;
        justify-content: space-between;
        position: static;
        border-radius: var(--radius-md);
    }

    .table--cards tfoot td::before {
        content: attr(data-label);
        color: var(--text-muted);
        font-size: var(--text-xs);
        text-transform: uppercase;
    }
}

/* ---------------------------------------------------------------------------
   Scroll affordance. A wide table that overflows shows a fading edge so it is
   obvious there is more to the side. animation-timeline would be cleaner but
   is not universally supported; a static gradient on the wrapper is enough.
   --------------------------------------------------------------------------- */
@media (max-width: 768px) {
    .table-wrap--fade {
        background:
            linear-gradient(to right, var(--surface-raised) 30%, transparent),
            linear-gradient(to left, var(--surface-raised) 30%, transparent) 100% 0,
            radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, 0.35), transparent),
            radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.35), transparent) 100% 0;
        background-repeat: no-repeat;
        background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
        background-attachment: local, local, scroll, scroll;
    }
}
