/* ─────────────────────────────────────────────────────────────────────────────
   Expenses — the draft claim's composer borrows the Timesheet's (.ts-composer,
   timesheets.css): one compact row of fields above the table instead of boxes
   squeezed into its cells. Only the row's columns and the field labels are here.
   ───────────────────────────────────────────────────────────────────────────── */
.ex-composer { margin-bottom: var(--spacing-4); }
.ex-composer__row {
    display: grid;
    grid-template-columns: 150px minmax(0, 1.6fr) minmax(0, 1fr) repeat(3, 100px) auto;
    gap: var(--spacing-2);
    align-items: end;
}

.ex-composer__evidence {
    height: 40px;
    border-radius: 8px;
    padding-inline: 18px;
    position: relative;
    min-width: 0;
    cursor: pointer;
}
/* The real file input: out of sight but still focusable, so Tab reaches it and the label shows its focus ring. */
.ex-composer__file {
    position: absolute;
    width: 1px; height: 1px;
    opacity: 0;
    overflow: hidden;
}
.ex-composer__evidence:focus-within { outline: 2px solid var(--color-primary); outline-offset: 2px; }
/* A long file name is cut short rather than widening the row. */
.ex-composer__file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ex-composer__field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ex-composer__field[hidden] { display: none; }
/* A mileage type: Miles joins the row before Claimed, which turns read-only and shows miles × the rate. */
.ex-composer__row.is-mileage { grid-template-columns: 150px minmax(0, 1.6fr) minmax(0, 1fr) repeat(4, 100px) auto; }
.ex-composer__amount[readonly] { background: var(--color-surface-alt); color: var(--color-text-secondary); }
.ex-composer__label { font-size: 11px; font-weight: var(--font-weight-medium); color: var(--color-text-secondary); }
/* Fixed at the Timesheet's 40px, so the vertical padding from forms.css goes — it left too little room and clipped the text. */
.ex-composer .input, .ex-composer .select { padding-block: 0; }
.ex-composer .select { height: 40px; border-radius: 8px; font-size: var(--font-size-sm); }
.ex-composer__amount { text-align: right; font-variant-numeric: tabular-nums; }

/* The draft card clips its contents (.card--flush); the job picker's dropdown has to escape it, as on the Timesheet.
   It's spaced off the claims below it. */
.card[data-expense-draft] { overflow: visible; margin-bottom: var(--spacing-5); }
/* The claims table, spaced off the imported history below it. */
.card[data-expense-claims] { margin-bottom: var(--spacing-5); }
/* The approvals queue's summary cards, spaced off the first claim below them. */
.ex-approval-stats { margin-bottom: var(--spacing-5); }

/* Approvals: the people list on the left, the cards and claims on the right. The list stays in view while the
   claims scroll, and scrolls itself when there are more people than fit. */
.ex-approvals { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: var(--spacing-5); align-items: start; }
.ex-people { position: sticky; top: 0; display: flex; flex-direction: column; max-height: calc(100vh - 160px); }
.ex-people__search { padding: var(--spacing-3); border-bottom: 1px solid var(--color-border); }
.ex-people__search .input { width: 100%; }
.ex-people__list { overflow-y: auto; }
.ex-people__item {
    display: block; width: 100%; padding: var(--spacing-3) var(--spacing-4);
    border: 0; border-bottom: 1px solid var(--color-border); background: none;
    font: inherit; text-align: left; cursor: pointer;
}
.ex-people__item:hover { background: var(--color-surface-alt); }
.ex-people__item[aria-pressed="true"] { background: var(--color-primary-soft); box-shadow: inset 3px 0 0 var(--color-primary); }
.ex-people__item[hidden] { display: none; }
.ex-people__name { display: block; font-weight: var(--font-weight-semibold); color: var(--color-text); }
.ex-people__meta { display: block; margin-top: 2px; font-size: var(--font-size-sm); color: var(--color-text-muted); }
.ex-people__empty { padding: var(--spacing-4); font-size: var(--font-size-sm); color: var(--color-text-muted); text-align: center; }

/* An approvals claim card: spaced off the next one. Its head has the claim number with who/when/how much under
   it on the left, and what's left to decide with Approve all on the right; on a narrow column the right side
   drops under the left. */
.ex-approval { margin-bottom: var(--spacing-5); }
.ex-approval__head { flex-wrap: wrap; }
.ex-approval__heading { min-width: 0; }
.ex-approval__title { display: flex; align-items: center; gap: var(--spacing-2); white-space: nowrap; }
.ex-approval__meta { margin-top: 2px; font-size: var(--font-size-sm); color: var(--color-text-muted); }
.ex-approval__meta strong { color: var(--color-text-secondary); font-weight: var(--font-weight-semibold); }
.ex-approval__head-actions { display: flex; align-items: center; gap: var(--spacing-3); flex-shrink: 0; }
/* The line rows: the date on one line, evidence as a small line under the type, the row's buttons kept together. */
.ex-approval__date { white-space: nowrap; }
.ex-approval__sub { margin-top: 2px; font-size: var(--font-size-xs); color: var(--color-text-muted); }
.ex-approval__actions { white-space: nowrap; }
.ex-approval__actions .btn + .btn, .ex-approval__actions form + .btn { margin-left: var(--spacing-1); }
.ex-approval__reason { display: block; width: 100%; margin-bottom: var(--spacing-2); }
/* Accept's form sits inline beside Reject…; a rejected line's reason sits under its badge. */
.ex-approval__inline { display: inline; }
.ex-approval__decision-reason { margin-top: var(--spacing-1); font-size: var(--font-size-sm); }
/* The claims' pager sits under the last card on the page, not inside one, so it drops the card padding.
   .pagination's display: flex would otherwise beat the hidden attribute. */
.ex-approvals__pager { padding: 0; }
.ex-approvals__pager[hidden] { display: none; }

/* Narrower: the list goes above the claims, shorter. */
@media (max-width: 1024px) {
    .ex-approvals { grid-template-columns: 1fr; }
    .ex-people { position: static; max-height: 280px; }
}
@media (max-width: 640px) {
    .ex-approval-stats { grid-template-columns: 1fr; }
    .ex-people__search .input { font-size: 16px; }
}
/* The draft card's head, right-hand side: the line count, then New Expense Line. */
.ex-draft__actions { display: flex; align-items: center; gap: var(--spacing-3); }
/* A form that only wraps its button (Submit claim, a line's ✕): no box of its own, so the button lays out as if
   the form weren't there. */
.ex-form-contents { display: contents; }
/* The imported history's head is its <details> toggle. */
.card[data-expense-imported] > .card__head { cursor: pointer; }

/* The line lifted into the composer waits in the table, dimmed, with its actions gone — as on the Timesheet. */
.data-table tr[data-ex-editing] { opacity: 0.4; }

/* ── Your claims: one row per claim, opening to its lines ─────────────────────────────────────────────── */
/* The outcome chips, between the card head and the table. */
.ex-claims__filters {
    display: flex; flex-direction: column; gap: var(--spacing-3);
    padding: 0 var(--spacing-5) var(--spacing-4);
}
.ex-filter { display: flex; flex-wrap: wrap; gap: var(--spacing-2); }
.ex-filter__chip {
    display: inline-flex; align-items: center; gap: var(--spacing-2);
    padding: var(--spacing-1-5) var(--spacing-4);
    border: 1px solid var(--color-border); border-radius: var(--radius-pill);
    background: var(--color-surface);
    font-family: inherit; font-size: var(--font-size-sm); font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary); cursor: pointer;
}
.ex-filter__chip:hover { background: var(--color-surface-alt); }
.ex-filter__chip b { color: var(--color-text); font-weight: var(--font-weight-semibold); }
.ex-filter__chip.is-active { background: var(--color-text); border-color: var(--color-text); color: var(--color-surface); }
.ex-filter__chip.is-active b { color: var(--color-surface); }

/* A claim row opens on a click anywhere along it; the arrow turns down while it's open. */
.ex-claims .ex-claim { cursor: pointer; }
.ex-claim__toggle {
    display: inline-grid; place-items: center;
    width: 20px; height: 20px; margin-right: var(--spacing-2); padding: 0;
    border: 0; background: transparent; color: var(--color-text-muted); cursor: pointer;
    vertical-align: middle; transition: transform 0.15s ease;
}
.ex-claim__toggle[aria-expanded="true"] { transform: rotate(90deg); }
.ex-claim__no { font-weight: var(--font-weight-semibold); }
/* The small grey second line in a cell: "2/3 accepted · 1 rejected", a rejection reason. */
.ex-claim__sub { margin-top: 2px; font-size: var(--font-size-xs); color: var(--color-text-muted); }

/* The open claim's lines: a tinted table of their own in the row under the claim, on the claims table's columns
   and padding so they line up. The date column steps in past the toggle, under the claim number. */
.data-table tbody tr.ex-claim__lines > td { padding: 0; background: var(--color-surface-alt); }
.ex-lines { background: var(--color-surface-alt); }
/* The claims table's widths (its widths="18,13,21,12,10,12,14" in Expenses.cshtml) — keep the two in step. */
.ex-lines > colgroup > col:nth-child(1) { width: 18%; }
.ex-lines > colgroup > col:nth-child(2) { width: 13%; }
.ex-lines > colgroup > col:nth-child(3) { width: 21%; }
.ex-lines > colgroup > col:nth-child(4) { width: 12%; }
.ex-lines > colgroup > col:nth-child(5) { width: 10%; }
.ex-lines > colgroup > col:nth-child(6) { width: 12%; }
.ex-lines > colgroup > col:nth-child(7) { width: 14%; }
.ex-lines thead th { background: transparent; }
.ex-lines thead th:first-child,
.ex-lines tbody td:first-child { padding-left: calc(var(--spacing-5) + 20px + var(--spacing-2)); }

/* Narrower screens: date and job share a line, then type and the amounts, then Save across the bottom. */
@media (max-width: 1100px) {
    .ex-composer__row, .ex-composer__row.is-mileage { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .ex-composer__row .ts-composer__add { grid-column: 1 / -1; }
}

/* Phones: two columns. Job gets a row of its own, and `dense` pulls Type up beside Date into the gap that leaves.
   The amounts pair up below; Evidence goes across on its own, or beside VAT when Miles has joined the amounts.
       Normal:  Date | Type              Mileage:  Date | Type
                Job ──────                         Job ──────
                Claimed | VAT                      Miles | Claimed
                Evidence ─────                     VAT | Evidence
                Save ─────                         Save ─────          */
@media (max-width: 640px) {
    .ex-composer__row, .ex-composer__row.is-mileage {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        grid-auto-flow: row dense;
    }
    .ex-composer__row .ex-composer__field--job { grid-column: 1 / -1; }
    .ex-composer__row .ts-composer__add { grid-column: 1 / -1; }
    .ex-composer__row:not(.is-mileage) .ex-composer__field--evidence { grid-column: 1 / -1; }
    /* 16px or more, or iPhone Safari zooms the page in when a field is tapped. */
    .ex-composer input, .ex-composer select { font-size: 16px; }
}

/* ── Phones: the rest of the page ────────────────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {
    /* Heads wrap rather than squeeze: Submit claim drops under the title, New Expense Line under "Your draft claim". */
    .page-head:has(#submit-expense-claim),
    .card[data-expense-draft] > .card__head,
    .card[data-expense-claims] > .card__head,
    .card[data-expense-imported] > .card__head,
    .ex-draft__actions { flex-wrap: wrap; }

    /* The outcome chips: one row that scrolls sideways, instead of three rows of wrapped pills. */
    .ex-filter { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
    .ex-filter::-webkit-scrollbar { display: none; }
    .ex-filter__chip { flex-shrink: 0; }

    /* Tables become cards (.ex-cards): no header row, each row a card, each cell a line with its data-label on the
       left and the value on the right. Child combinators throughout, so a claim's rules don't reach the lines
       table nested inside it — that one is .ex-cards too, and gets its own. */
    .ex-cards, .ex-cards > tbody { display: block; }
    .ex-cards > thead { display: none; }
    .ex-cards > tbody > tr { display: block; padding: var(--spacing-3) var(--spacing-4); border-bottom: 1px solid var(--color-border); }
    /* display: block would otherwise beat the hidden attribute, and every claim's lines would show. */
    .ex-cards > tbody > tr[hidden] { display: none; }
    .ex-cards > tbody > tr > td {
        display: flex; justify-content: space-between; align-items: flex-start; gap: var(--spacing-3);
        padding: var(--spacing-1) 0; border: 0; text-align: right;
    }
    .ex-cards > tbody > tr > td::before {
        content: attr(data-label); flex-shrink: 0; text-align: left;
        font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold);
        letter-spacing: var(--letter-spacing-label); text-transform: uppercase; color: var(--color-text-muted);
    }
    .ex-cards > tbody > tr > td:not([data-label])::before { content: none; }
    .ex-cards > tbody > tr > td.ex-cards__empty { display: none; }
    .ex-cards > tbody > tr > td.table-empty { display: block; text-align: center; }

    /* A claim card's head: the toggle and the number, bigger, on the left. The whole card still opens it. */
    .ex-cards > tbody > tr > td.ex-cards__head { justify-content: flex-start; align-items: center; padding-bottom: var(--spacing-2); font-size: var(--font-size-md); }
    .ex-claim__toggle { width: 32px; height: 32px; margin-left: calc(-1 * var(--spacing-2)); margin-right: var(--spacing-1); }

    /* A draft line's Edit and ✕: bigger, further apart, on their own line at the foot of the card. */
    .ex-cards > tbody > tr > td.ex-cards__actions { justify-content: flex-end; padding-top: var(--spacing-2); }
    .ex-cards__actions .ts-entry__actions { gap: var(--spacing-2); }
    .ex-cards__actions .ts-entry__action { padding: var(--spacing-2) var(--spacing-3); font-size: var(--font-size-sm); }

    /* An open claim's lines: small white cards on the tinted strip under the claim's card. */
    .ex-cards > tbody > tr.ex-claim__lines { padding: 0 var(--spacing-3) var(--spacing-3); background: var(--color-surface-alt); }
    .ex-cards > tbody > tr.ex-claim__lines > td { display: block; padding: 0; }
    .ex-lines.ex-cards > tbody > tr {
        margin-top: var(--spacing-2); padding: var(--spacing-2) var(--spacing-3);
        background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md);
    }
    /* The desktop indent that lines the date up under the claim number has nothing to line up with here. */
    .ex-lines.ex-cards > tbody > tr > td { padding-left: 0; }
}