/*
 * Tables.
 *
 * No zebra and no vertical rules between columns: the eye follows a row without them, and both
 * would fight the row highlighting, which carries real meaning here.
 *
 * The header is sticky, because the tables in this project are long (core.md §5.5). The
 * box scrolls sideways on its own so that the page never does at any phone width.
 */

/*
 * The box scrolls, not the page: sideways because a wide table must never make the page
 * scroll sideways, and downwards because that is what makes the heading stay on screen.
 *
 * A sticky heading sticks to its scroll container. While the box scrolled only sideways, the
 * container it stuck to never moved vertically and the heading scrolled away with the rows —
 * which is what core.md §5.5 asks not to happen. Capped rather than fixed in height, so
 * a table of three rows takes three rows.
 */
.app-table-box {
    max-height: var(--table-height);
    overflow: auto;
    /* Only sideways: a finger that reaches the bottom of the table goes on scrolling the page. */
    overscroll-behavior-x: contain;
    /* The containing block of what is absolutely placed inside (a disabled action's hidden reason, .app-sr):
       without it that reason stands at the table's far edge relative to the page and scrolls the page sideways. */
    position: relative;
}

.app-table {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: var(--numeric);
}

.app-table th {
    position: sticky;
    top: 0;
    z-index: 1;
    padding: var(--space-3) var(--space-4);
    /* An inset shadow rather than a border: with border-collapse the line belongs to the
       table, not to the cell, so it stays behind while the sticky heading moves and the
       heading ends up floating over the rows with nothing between them. */
    box-shadow: inset 0 -1px 0 var(--border);
    /* Opaque on purpose: rows scroll underneath it. */
    background: var(--surface);
    color: var(--text-3);
    font-size: var(--fs-caption);
    font-weight: var(--fw-regular);
    text-align: left;
    white-space: nowrap;
}

.app-table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

/* The first column carries the name of the row and is set a shade heavier. */
.app-table td:first-child {
    font-weight: var(--fw-medium);
}

.app-table tbody tr:last-child td {
    border-bottom: 0;
}

/*
 * A figure is aligned to the right so that digits line up between rows — but only where the
 * column is wide enough for the heading to sit above its own numbers. In a narrow column the
 * heading ends up beside a neighbouring column and nothing says which figures are its own, so
 * there both the heading and the figures are centred.
 */
.app-table__num {
    text-align: right;
    white-space: nowrap;
}

.app-table th.app-table__narrow,
.app-table td.app-table__narrow {
    width: 1%;
    text-align: center;
    white-space: nowrap;
}

/*
 * A narrow column is given a width instead of being left to the browser.
 *
 * A column sized by its content changes width from page to page, and in a table where one
 * column is a comment the browser gives that column everything and pushes the figures to the
 * far edge — the eye then walks the row (core.md §5.1). Every short column of the project is
 * sized here, so the same data stands in the same place on every page. Add the columns this
 * project has beside them; do not size a column from a page stylesheet.
 */
.app-table th.app-table__col--date,
.app-table td.app-table__col--date {
    width: 112px;
    text-align: center;
    white-space: nowrap;
}

/*
 * The figures are aligned to the right, which is where a column of numbers belongs
 * (core.md §5.2): digits then line up under digits, units under units, and the eye
 * compares two amounts without reading either of them.
 *
 * Centring was tried first and failed for the same reason: a centred figure moves sideways
 * as its length changes, which is the floating line the same rule forbids.
 */
.app-table th.app-table__col--amount,
.app-table td.app-table__col--amount {
    width: 148px;
    text-align: right;
    white-space: nowrap;
}

/*
 * The currency of the amount beside it, in a cell of its own.
 *
 * A list that mixes currencies has to say which one every figure is in, and saying it inside the
 * amount cell would push the digits sideways from row to row — the drift core.md §5.2 forbids.
 * Narrow, muted and left-aligned: it stands right after the figure and takes no attention.
 */
.app-table th.app-table__col--currency,
.app-table td.app-table__col--currency {
    width: 56px;
    color: var(--text-3);
    font-size: var(--fs-caption);
    white-space: nowrap;
}

.app-table th.app-table__col--moment,
.app-table td.app-table__col--moment {
    width: 150px;
    text-align: center;
    white-space: nowrap;
}

.app-table th.app-table__col--state,
.app-table td.app-table__col--state {
    width: var(--w-col-narrow);
    text-align: center;
}

/*
 * A list where the name is what the eye looks for (the document journal, owner review R5).
 *
 * The name column takes everything the compact ones leave, so a long name wraps instead of the
 * table scrolling; it is capped at three lines (the clamp), so one name never makes a row tall.
 * The columns around it are as wide as their content, with the small side padding of --compact.
 */
.app-table th.app-table__col--wide,
.app-table td.app-table__col--wide {
    width: 100%;
    min-width: 190px;
}

.app-table th.app-table__col--fit,
.app-table td.app-table__col--fit {
    width: 1%;
    white-space: nowrap;
}

.app-table--compact th,
.app-table--compact td {
    padding-inline: var(--space-1);
}

/* The figures of a compact table are as wide as their digits: the room goes to the name column. */
.app-table--compact th.app-table__col--amount,
.app-table--compact td.app-table__col--amount {
    width: 1%;
}

/*
 * The journal must fit its box with a classic scrollbar (Firefox takes ~15 px of the page for it): the currency stands
 * right after its figure and the row's buttons keep only the side toward the edge, ~20 px of the table's minimum width.
 */
.app-table--compact th.app-table__col--currency,
.app-table--compact td.app-table__col--currency {
    padding-left: 0;
}

.app-table--compact th.app-table__actions,
.app-table--compact td.app-table__actions {
    padding-inline: 0 var(--space-0);
}

.app-table__clamp {
    display: -webkit-box;
    overflow: hidden;
    overflow-wrap: anywhere;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
}

/*
 * A list of text that may be long in every column (the clients, map Б.Б1): a fixed layout, so a long value is cut
 * with an ellipsis inside its column instead of widening the table (core.md §4.5, §5.1). The name takes what the
 * other columns leave: 920 − 160 (Tax ID) − 300 (email) − 190 (phone) − 72 (the delete) = 198 px at the narrowest;
 * below that the box scrolls sideways (core.md §5.5).
 */
.app-table--fixed {
    min-width: 920px;
    table-layout: fixed;
}

.app-table th.app-table__col--code,
.app-table td.app-table__col--code {
    width: 160px;
}

.app-table th.app-table__col--email,
.app-table td.app-table__col--email {
    width: 300px;
}

/* An international number with its spaces, «+995 32 222 3344», whole. */
.app-table th.app-table__col--phone,
.app-table td.app-table__col--phone {
    width: 190px;
}

/* One icon button and the cell's side padding: a 1% width means nothing in a fixed layout. */
.app-table--fixed th.app-table__actions,
.app-table--fixed td.app-table__actions {
    width: calc(var(--icon-btn) + 2 * var(--space-4));
}

/*
 * The payments table (Ж.Б3, 8 columns and the three action slots): a fixed layout with explicit widths, so the same
 * data stands in the same place whatever a row holds (core.md §5.1). The surplus goes to the Flag column, the one text
 * column, which wraps instead of being cut; every other long value (an email, a code, a transaction) wraps anywhere
 * in its own column and keeps its tooltip. Widths, border-box, with the compact side padding of 8 px each side:
 *   Date 112 + User 160 + Promo code 100 + State 110 = 482, plus actions 132 (3 × icon-button
 *   40 + 3 gaps of 4) = 614 px fixed; the merged amounts column (price / discount / paid, one currency on each line)
 *   156 and the PRO column (granted / end date, two lines) 112 = 268.
 *   The 156 is measured in the browser: the widest line of the grid, «−1,049.00 EUR» (mark track 9.2 + figure 72.9 +
 *   currency 30.2 + two gaps of 12 = 136.2), plus the cell's 2 × 8 of padding = 152.2, up to a multiple of 4.
 *   Flag at least 171 px → the table is never narrower than 614 + 268 + 171 = 1053 px = the box at a 1440 px window
 *   (1068 px, 1053 with a 15 px scrollbar): no sideways scroll there, the surplus is the Flag's.
 *   On a coarse pointer the buttons are the touch size (3 × 48 + 12 = 156 px, 24 more): 638 + 268 + 171 = 1077 px,
 *   24 px of sideways scroll inside the box (core.md §5.5; the page never scrolls).
 *   The transaction id is in the search Б2 and the opened row's detail Б12, not in a column.
 * Wider than the box the box scrolls sideways on its own; from there every px more is the Flag column's.
 */
.app-table--payments {
    min-width: 1053px;
    table-layout: fixed;
}

.app-table--payments td {
    overflow-wrap: anywhere;
}

/* A heading breaks over two lines instead of being cut («Price / discount / paid»). */
.app-table--payments th,
.app-table--payments th.app-table__col--amount {
    white-space: normal;
}

.app-table--payments th.app-table__col--user,
.app-table--payments td.app-table__col--user {
    width: 160px;
}

.app-table--payments th.app-table__col--promo,
.app-table--payments td.app-table__col--promo {
    width: 100px;
}

/* Three amount lines of one grid; they end at the cell's right edge. The width is the widest line, see above. */
.app-table--payments th.app-table__col--amount,
.app-table--payments td.app-table__col--amount {
    width: 156px;
}

/* The Flag column has no width of its own: the surplus of the table is its. */
.app-table--payments th.app-table__col--wide,
.app-table--payments td.app-table__col--wide {
    width: auto;
    min-width: 0;
}

.app-table--payments th.app-table__actions,
.app-table--payments td.app-table__actions {
    width: calc(3 * var(--icon-btn) + 3 * var(--space-0));
}

@media (pointer: coarse) {
    .app-table--payments {
        min-width: 1077px;
    }

    .app-table--payments th.app-table__actions,
    .app-table--payments td.app-table__actions {
        width: calc(3 * var(--icon-btn-touch) + 3 * var(--space-0));
    }
}

/* A value on one line, cut with an ellipsis; the tooltip says it in full only while it is cut. */
.app-table__cut,
.app-table__opener {
    display: block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A name that opens its form in the dialog (a button, not a link: there is no page to go to). */
.app-table__opener {
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.app-table__opener:hover {
    color: var(--accent-link-hover);
}

/* A figure that opens its form (Ж.Б4 «Available»): it keeps the right edge of its column like every amount. */
.app-table__col--amount .app-table__opener {
    margin-inline-start: auto;
    text-align: right;
}

/* An opener that will refuse now (core.md §9.5): the figure as text, the tooltip with the reason still reachable. */
.app-table__opener[aria-disabled='true'],
.app-table__opener[aria-disabled='true']:hover {
    color: inherit;
    cursor: not-allowed;
}

/* A negative figure stays red as a button too: this file loads after badge.css, so the opener's colour would win. */
.app-table__opener.app-amount--negative,
.app-table__opener.app-amount--negative:hover {
    color: var(--negative);
}

/* The name is the row's way in: a finger needs the touch height, as the card's opener has (core.md §19.1). */
@media (max-width: 720px) {
    .app-table__opener {
        min-height: var(--control-touch);
    }
}

/* Actions sit next to their own row (core.md §4.7), pinned to the right edge. */
.app-table__actions {
    width: 1%;
    white-space: nowrap;
}

.app-table__actions > div {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-0);
}

/* An archived row keeps its colour and its text stays legible on it (core.md §5.8). */
.app-table tbody tr.app-row--archived td {
    color: var(--text-4);
}

/* The empty state prints a sentence, not an illustration. */
.app-empty {
    padding: var(--space-6) var(--space-4);
    color: var(--text-3);
    text-align: center;
}

/* --- Pager --------------------------------------------------------------------------- */

/*
 * Pagination as the kit draws it: the position on the left, the pages on the right.
 *
 * The current page carries the soft fill of a pressed filter button and nothing louder —
 * there is no accent background in pagination.
 */
.app-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    /* Continuation of the table above it, so the small step. */
    padding-top: var(--space-2);
}

.app-pager__info {
    color: var(--text-3);
    font-size: var(--fs-caption);
    font-variant-numeric: var(--numeric);
}

.app-pager__pages {
    display: flex;
    align-items: center;
    gap: var(--space-0);
}

.app-pager__page {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--control-sm);
    height: var(--control-sm);
    padding: 0 var(--space-1);
    border-radius: var(--radius-control);
    color: var(--text-2);
    font-size: var(--fs-body);
    font-variant-numeric: var(--numeric);
    text-decoration: none;
    transition: background var(--transition);
}

a.app-pager__page:hover {
    background: var(--surface-2);
    color: var(--text-2);
    text-decoration: none;
}

.app-pager__page--on {
    background: var(--accent-soft-2);
    color: var(--accent);
    font-weight: var(--fw-semibold);
}

/* At the edge the step stays in place as a dead glyph: the row must not shift under the hand. */
.app-pager__page--off {
    color: var(--text-disabled);
}

.app-pager__gap {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: var(--control-sm);
    color: var(--text-4);
}

/* The sample picture of a row (Themes): the file is 2x the drawn size, so it stays sharp on dense screens. */
.app-table__sample {
    display: block;
    max-width: 100%;
    height: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-tile);
}

/*
 * A label edited where it is shown (Ж.Б10): the input takes the width of its column and the mark
 * «falls back to English» stands under it, so the placeholder text keeps the whole line.
 */
.app-labels__input {
    width: 100%;
}

.app-labels .app-actions {
    margin-top: var(--space-3);
}

.app-labels__input + .app-badge {
    margin-top: var(--space-half);
}

/*
 * On a phone the three columns do not fit (core.md §19.1): each row stacks, the key and the English text
 * above and the input below at the full width, the mark under it. The heading row goes; every input
 * carries its own aria-label.
 */
@media (max-width: 720px) {
    .app-labels .app-table thead {
        display: none;
    }

    .app-labels .app-table,
    .app-labels .app-table tbody {
        display: block;
    }

    .app-labels .app-table tr {
        display: flex;
        flex-wrap: wrap;
        border-bottom: 1px solid var(--border);
    }

    .app-labels .app-table tbody tr:last-child {
        border-bottom: 0;
    }

    .app-labels .app-table td {
        border-bottom: 0;
    }

    .app-labels .app-table td:last-child {
        flex: 1 0 100%;
        padding-top: 0;
    }

    .app-labels .app-badge {
        white-space: normal;
    }
}
