/* The transaction list (lean-rollout ticket 107). Every colour, size, radius, weight and
   duration below is a token from finance_app/static/tokens.css, generated from
   tokens/moneyos.json; this sheet defines none of its own and contains no literal.

   Everything is scoped to #transactions-panel or to a `tx-` class this page owns, because
   three other pages are being built against the same shell this week and a rule that
   reached outside this panel would land on one of them. Ticket 118 and ticket 121 already
   collided once over a shared class name; nothing here is a name another page could pick.

   One thing leads: the total for the whole filter is set at the display step over the
   body step, and every other figure on the page is quieter than it.

   TICKET 154 (design parity with A): the summary is the prototype's -- total, a divider,
   distinct transfers, the export at the end of the row, on one row at phone width too
   (TD-14, TD-19); the filters are two rows at desktop with the range control's compact
   form beside the basis pair (TD-01); and the list changes shape by the width of ITS OWN
   REGION rather than the viewport (TD-03), because the sidebar still takes width at 1024
   and a viewport rule left a seven-column table in a region too narrow for it. */

#transactions-panel{display:flex;flex-direction:column;gap:var(--space-16)}

/* --- The summary. It covers every page of the filter, which is why it is the one figure
   set large: a person reading this page is reading that number. --- */
.tx-summary{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-12) var(--space-32);
  margin:0;padding:var(--space-20) var(--space-24);background:var(--color-surface-card);
  border:1px solid var(--color-border-default);border-radius:var(--radius-card-lg);box-shadow:var(--shadow-sm)}
.tx-summary-lead{flex:0 1 auto;min-inline-size:0;display:flex;flex-direction:column;gap:var(--space-4)}
.tx-summary-figure{margin:0;display:flex;align-items:baseline;gap:var(--space-8);flex-wrap:wrap;
  color:var(--color-text-primary);font-size:var(--text-display-sm);font-weight:var(--weight-semibold);
  line-height:var(--leading-snug);letter-spacing:-0.02em;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.tx-summary-unit{font-size:var(--text-md);font-weight:var(--weight-regular);color:var(--color-text-secondary);letter-spacing:normal}
.tx-summary-unit[hidden]{display:none}
/* The count is what the total is made of, beside it and behind a divider, the
   prototype's "48 ธุรกรรมไม่ซ้ำ". Without a figure it keeps its place and shows nothing,
   so the card does not change shape when the figures land. */
.tx-summary-count{display:flex;flex-direction:column;justify-content:center;gap:var(--space-2);
  min-inline-size:0;margin:0;align-self:stretch;
  padding-inline-start:var(--space-32);border-inline-start:1px solid var(--color-border-default)}
.tx-summary-count strong{font-size:var(--text-xxl);font-weight:var(--weight-semibold);line-height:var(--leading-snug);
  color:var(--color-text-primary);font-variant-numeric:tabular-nums}
.tx-summary-count span{font-size:var(--text-sm);color:var(--color-text-secondary)}
.tx-summary-count[data-state=empty]{visibility:hidden}
.tx-summary-foot{flex:1 1 100%;display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-8) var(--space-16);min-inline-size:0}
.tx-summary-note{flex:1 1 var(--size-280);margin:0;font-size:var(--text-sm);color:var(--color-text-secondary);max-width:none}
/* TICKET 108: the export sits at the END of the summary row, which is where the
   prototype puts it -- the act beside the scope it acts on -- and it drops to its own
   full-width row at phone width rather than squeezing the count. It is a secondary
   button: the primary action of this page is opening a record, not taking a copy of it
   away, and one action role wears one variant product-wide. */
.tx-export{flex:0 0 auto;margin-inline-start:auto;display:inline-flex;align-items:center;
  gap:var(--space-8);min-height:var(--size-44);padding-inline:var(--space-16)}
/* The export reports the EXPORT. Its own line, under the figures, never on top of one. */
.tx-export-status{flex:1 1 100%;margin:0;font-size:var(--text-sm);color:var(--color-text-secondary);max-width:none}
.tx-export-status[data-state=error]{color:var(--color-feedback-error-text)}

/* --- Freshness. Five states, and the words carry each one; the colour only supports it.
   TICKET 154 (TD-16): `ready` says when the figures were read ("ข้อมูล ณ 14:32 น."),
   quietly, at the end of the note under the figures it dates -- the module moves this
   line into the summary card, since the as-of belongs to those figures and the
   prototype prints it beside the heading rather than as a row of its own. Every other
   state is a banner across the card. --- */
.tx-freshness{flex:1 1 100%;display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-8);
  margin:0;padding:var(--space-6) var(--space-12);border:1px solid var(--color-border-default);
  border-radius:var(--radius-control);background:var(--color-surface-sunken);
  color:var(--color-text-secondary);font-size:var(--text-sm);max-width:none;min-block-size:var(--size-36)}
.tx-freshness[data-state=ready]{flex:0 0 auto;margin-inline-start:auto;min-block-size:0;padding:0;
  background:transparent;border-color:transparent;font-size:var(--text-xs)}
/* Loading is a short line and sits where "ready" will, at the end of the note's row, so
   the card -- and the filters under it -- barely move when the figures land (TD-18). */
.tx-freshness[data-state=loading]{flex:0 1 auto;margin-inline-start:auto}
.tx-freshness[data-state=ready]::before{content:"";inline-size:var(--space-6);block-size:var(--space-6);
  border-radius:var(--radius-pill);background:var(--color-action-primary)}
.tx-freshness[data-state=partial]{background:var(--color-feedback-warning-bg);
  border-color:var(--color-border-lead);color:var(--color-feedback-warning-text)}
.tx-freshness[data-state=stale]{background:var(--color-feedback-hold-bg);
  border-color:var(--color-border-lead);color:var(--color-feedback-hold-text)}
.tx-freshness[data-state=error]{background:var(--color-feedback-error-bg);
  border-color:var(--color-border-danger);color:var(--color-feedback-error-text)}
.tx-retry{min-height:var(--size-36);padding-inline:var(--space-12);font-size:var(--text-sm)}
/* A figure that is not there cannot be clicked at. */
#transactions-panel[data-transactions-state=loading] .tx-table-wrap,
#transactions-panel[data-transactions-state=error] .tx-table-wrap{pointer-events:none}

/* --- The panel that holds the toolbar, the list and its pager. It is a size container:
   the list below changes shape by the width of this region, not of the window. --- */
.tx-panel{border:1px solid var(--color-border-default);border-radius:var(--radius-card);
  background:var(--color-surface-card);overflow:hidden;container:tx-panel / inline-size}
/* Two rows, and the split is what the filters mean rather than what fits: WHEN (the
   basis and its range) above WHAT (the search, the account, the sender and the status).
   TICKET 154: the WHEN row is ONE row now. `.tx-when` used to be declared a second time
   further down for the time under a row's id, and that later `display:block` stacked the
   basis pair over the range at every width (TD-01); the row's time is `.tx-row-when`. */
/* A one-column GRID, not a column flexbox, and both halves are load-bearing (TD-18).
   The app's `form` rule says `align-items:flex-end`, which in the column flexbox this
   was right-aligned each row to its own content width: while loading, with the account
   and sender selects still empty, the search row was narrower than the panel and started
   162 px in, then jumped left when the options arrived. And a column flexbox sized the
   WHEN row from a pass in which the range control had wrapped, so the row stood 154 px
   tall around 71 px of controls (measured in Chrome); a grid track sizes it at its width. */
.tx-toolbar{display:grid;grid-template-columns:minmax(0,1fr);align-items:stretch;gap:var(--space-16);
  padding:var(--space-20) var(--space-24) var(--space-8);margin:0}
.tx-when{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--space-12) var(--space-24)}
.tx-what{display:flex;flex-wrap:wrap;align-items:flex-start;gap:var(--space-12) var(--space-16)}
/* Every filter is a label over its control, set as the prototype sets them: the body's
   smaller step, secondary ink, so the controls lead and the words stay readable. */
#transactions-filters label,#transactions-filters .filter-select>label,.tx-basis-title{
  font-size:var(--text-base);font-weight:var(--weight-medium);color:var(--color-text-secondary);line-height:var(--leading-normal)}
#transactions-filters label{min-inline-size:0}
#transactions-filters :is(input,select){color:var(--color-text-primary);font-size:var(--text-sm);font-weight:var(--weight-regular)}
/* The search grows most, but its basis is small enough that the four filters and the
   clear button share one row at 1280 in English as well as in Thai. */
.tx-search-field{flex:2 1 calc(var(--size-150) + var(--size-72))}
/* TD-13: an account reads "KBank · 2222225678", short name and full number, and the
   select is given room for both rather than the basis that cut it to the bank name. */
.tx-select{flex:1 1 calc(var(--size-150) + var(--size-28))}
.tx-search-box{position:relative;display:flex;align-items:center;min-inline-size:0}
.tx-search-box svg{position:absolute;inset-inline-start:var(--space-12);color:var(--color-text-secondary);pointer-events:none}
.tx-search-box input{padding-inline-start:var(--space-40)}
/* The two bases, side by side and named. A range that does not say which day it means is
   the defect F05 names, so the choice is a pressed pair and never an inferred default.
   Its label sits over it like every other filter's, and the pair is a control's height,
   so the row lines up at the controls' edge. */
.tx-basis{flex:0 0 auto;margin:0;padding:0;border:0;display:grid;grid-template-columns:auto auto;
  align-items:end;gap:var(--space-6) var(--space-8)}
.tx-basis-title{grid-column:1 / -1}
/* The unpressed half is a neutral outline and the pressed half carries the selected
   surface with the primary border, so the state is a shape and a word and not a colour
   alone. Both halves are buttons, so both are in the tab order. */
.tx-basis-option{min-height:var(--size-44);padding:var(--space-4) var(--space-16);
  border:1px solid var(--color-border-strong);border-radius:var(--radius-pill);
  background:var(--color-surface-card);color:var(--color-text-primary);
  font-size:var(--text-sm);font-weight:var(--weight-medium);white-space:nowrap}
.tx-basis-option:hover{background:var(--color-action-secondary-hover);border-color:var(--color-border-strong)}
.tx-basis-option:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}
.tx-basis-option[aria-pressed=true]{background:var(--color-surface-selected);
  border-color:var(--color-action-primary);color:var(--color-action-primary);
  font-weight:var(--weight-semibold)}
.tx-basis-option[aria-pressed=true]:hover{background:var(--color-surface-accent-chip)}
.tx-range{flex:1 1 calc(var(--size-280) + var(--size-150));min-inline-size:0}
.tx-status-filter{flex:1 1 var(--size-150);min-inline-size:0}
.tx-clear{flex:0 0 auto;align-self:center}
/* TICKET 154: the phone's "more filters" wrapper and button. Anywhere wider than a phone
   the wrapper is not a box at all, and its filters sit in the row as they always did. */
.tx-more-filters{display:contents}
.tx-more{display:none}
/* The one explanatory line under the toolbar: the range control writes it (TD-15). */
.tx-help{margin:0;max-width:none;padding:0 var(--space-24) var(--space-12);font-size:var(--text-sm);color:var(--color-text-secondary)}
.tx-scope{display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--space-4) var(--space-8);
  padding:var(--space-10) var(--space-24);background:var(--color-surface-sunken);
  border-block:1px solid var(--color-border-default);font-size:var(--text-sm);color:var(--color-text-secondary)}

/* --- The list. Money is read down a column: the amount is right aligned, tabular and
   never wraps mid-number. --- */
.tx-table-wrap{max-inline-size:100%;overflow:auto}
.tx-table-wrap table{min-width:0}
.tx-table-wrap th,.tx-table-wrap td{vertical-align:top}
.tx-table-wrap td{font-size:var(--text-sm)}
.tx-cell-label{display:none}
.tx-identity{min-inline-size:0}
.tx-id{display:inline-flex;align-items:center;min-height:var(--size-28);padding:var(--space-2) var(--space-4);
  margin-inline-start:calc(-1 * var(--space-4));background:transparent;border-color:transparent;
  color:var(--color-text-link);font-family:var(--font-mono);font-size:var(--text-sm);
  font-weight:var(--weight-semibold);white-space:nowrap}
.tx-id:hover{background:var(--color-action-ghost-hover);border-color:transparent;text-decoration:underline}
.tx-id:active{background:var(--color-action-ghost-hover);border-color:transparent}
.tx-id:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}
.tx-row-when{display:block;color:var(--color-text-secondary);font-size:var(--text-xs);font-variant-numeric:tabular-nums}
.tx-received{font-variant-numeric:tabular-nums;white-space:nowrap}
.tx-received-day{display:block}
.tx-sender strong{display:block;font-weight:var(--weight-semibold);overflow-wrap:anywhere}
.tx-sender small{display:block;color:var(--color-text-secondary);font-variant-numeric:tabular-nums}
/* TD-03: the account column never folds to one character a line. The renderer's own
   meta line breaks anywhere, which is right on a card and wrong in a column whose
   minimum it then sets; here it breaks between words, and the column keeps a floor. */
.tx-account{min-inline-size:calc(var(--size-150) + var(--size-28))}
.tx-account .bank-account-meta{overflow-wrap:break-word}
.tx-account-note{display:block;margin-block-start:var(--space-4);color:var(--color-text-secondary)}
.tx-archived{margin-block-start:var(--space-6)}
.tx-amount{text-align:right;white-space:nowrap}
.tx-amount-figure{display:block;font-size:var(--text-md);font-weight:var(--weight-semibold);
  color:var(--color-text-primary);font-variant-numeric:tabular-nums}
.tx-amount-unread{font-size:var(--text-sm);font-weight:var(--weight-regular);
  color:var(--color-text-secondary);white-space:normal}
/* The status word is one word and stays on one line here. `page-board.css` lets a badge
   wrap, which is right on a queue card and wrong in a table column: the word broke in
   half at 1280 (measured on the first render). It is allowed to wrap again on the card
   layout below, where the card is the width of the phone. */
.tx-status{min-inline-size:0}
.tx-status .badge{white-space:nowrap}
.tx-reason{display:block;margin-block-start:var(--space-4);color:var(--color-text-secondary)}
.tx-evidence{text-align:right}
.tx-evidence-button{display:inline-flex;align-items:center;gap:var(--space-6);min-height:var(--size-36);
  padding-inline:var(--space-12);font-size:var(--text-sm)}
.tx-foot{margin:0;font-size:var(--text-sm);color:var(--color-text-secondary)}
#transactions-scroll-hint{padding:var(--space-8) var(--space-24) 0}

/* --- The empty range. It owns the space it is in and says what to do next; the zero
   above it is a real zero, which is the whole point of the state. --- */
.tx-empty{padding:var(--space-48) var(--space-24);text-align:center;display:flex;
  flex-direction:column;align-items:center;gap:var(--space-12)}
.tx-empty h3{margin:0;font-size:var(--text-md);font-weight:var(--weight-semibold)}
.tx-empty p{margin:0;max-inline-size:52ch;font-size:var(--text-sm);color:var(--color-text-secondary)}

.tx-footer{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:var(--space-12);padding:var(--space-16) var(--space-24);
  border-block-start:1px solid var(--color-border-default);background:var(--color-surface-page);
  font-size:var(--text-sm);color:var(--color-text-secondary)}
.tx-footer span{min-inline-size:0}
.tx-pager{display:flex;gap:var(--space-8);flex-wrap:wrap}

/* TICKET 114: the `.tx-detail*` rules went with this page's own dialog. The one detail
   view is `finance_app/static/page-detail.css`; a row here opens it and draws none of
   it. */

/* --- The bank renderer (finance_app/static/bank-catalog.js, ticket 117). ------------
   TICKET 130: the rules themselves are in finance_app/static/bank-catalog.css, the one
   copy, loaded before this file. Ticket 121 wrote the first copy of them and recorded
   that a shared sheet was where they belonged; this page had the second. What stays
   here is what this page alone wants: a badge one step smaller than the all-accounts
   table's, because this is a row of fifty and the mark is one of eight columns rather
   than the first of five, the tighter gap that goes with it, and a card radius rather
   than a control radius, to match the table it sits in. */
#transactions-panel .bank-account{gap:var(--space-10)}
#transactions-panel .bank-icon{min-inline-size:var(--size-36);block-size:var(--size-36);
  padding-inline:var(--space-4);border-radius:var(--radius-card)}
#transactions-panel .bank-mark{inline-size:var(--space-24);block-size:var(--space-24)}

/* --- TICKET 154 (TD-03): the list by the width of its own region. ------------------
   The seven-column table needs about 960 px of region. TICKET 227: the withdrawal review's
   column makes eight, which took 1,056 px at 1280 (measured: the region is 982 there and the
   table scrolled sideways, cutting the evidence button), so the rows take over below
   1,100 px of region instead of 960. Below that each record is a ROW
   laid out on a grid -- the prototype's own shape at narrow widths, a divider between
   records rather than a boxed card -- in three columns while there is room for them, so
   a record at 1024 or 768 is two or three lines instead of the 588 px the squeezed table
   measured. The column heads are not drawn then, so the two cells that are a bare figure
   carry their own word. */
@container tx-panel (max-width: 1099px){
  #transactions-scroll-hint{display:none}
  .tx-table-wrap{overflow:visible}
  .tx-table-wrap table{display:block}
  .tx-table-wrap thead{display:none}
  .tx-table-wrap tbody{display:block}
  .tx-table-wrap tr{display:grid;
    grid-template-columns:minmax(0,1.2fr) minmax(0,1fr) minmax(0,1.3fr) auto auto;
    column-gap:var(--space-16);row-gap:var(--space-4);align-items:start;
    padding:var(--space-14) var(--space-24);border-block-end:1px solid var(--color-border-subtle)}
  .tx-table-wrap td{display:block;padding:0;border:0;min-inline-size:0}
  /* Three row tracks: the amount, then the status under it, then the received line. The
     id and its time span the first two, so the status sits under the amount rather than
     under however many lines the id took. */
  .tx-identity{grid-column:1;grid-row:1 / span 2}
  .tx-received{grid-column:1 / span 2;grid-row:3;white-space:normal;color:var(--color-text-secondary)}
  .tx-sender{grid-column:2;grid-row:1 / span 2}
  .tx-account{grid-column:3;grid-row:1 / span 3;min-inline-size:0}
  .tx-amount{grid-column:4;grid-row:1;text-align:end}
  .tx-status{grid-column:4;grid-row:2 / span 2;text-align:end}
  .tx-evidence{grid-column:5;grid-row:1 / span 3;text-align:end}
  /* An id is not a word: it breaks where the column ends, not at its hyphen. */
  .tx-id{white-space:normal;word-break:break-all;text-align:start;max-inline-size:100%}
  /* The received day and time on one line, after its word, under the transfer time. */
  .tx-received .tx-cell-label,.tx-received .tx-received-day,.tx-received .tx-row-when{display:inline;font-size:var(--text-xs)}
  .tx-received .tx-cell-label{margin-inline-end:var(--space-4);color:var(--color-text-caption);font-weight:var(--weight-semibold)}
  .tx-received .tx-row-when{margin-inline-start:var(--space-4);white-space:nowrap}
  /* The amount is the one right-aligned figure on the row, as in the prototype; its
     word is kept for a screen reader, which no longer has the column head. */
  .tx-amount .tx-cell-label{position:absolute;inline-size:1px;block-size:1px;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap}
  .tx-amount{position:relative}
  .tx-status .badge{white-space:normal}
}
/* A phone's region: two columns, the prototype's composition at 390 -- the id and its
   time with the amount beside them, the sender with the status beside it -- then the
   received line, the bank row and the evidence action across the whole row. The id
   wraps rather than running under the amount's word (TD-09). */
@container tx-panel (max-width: 559px){
  .tx-table-wrap tr{grid-template-columns:minmax(0,1fr) auto;column-gap:var(--space-12);row-gap:var(--space-8);
    padding:var(--space-14) var(--space-16)}
  .tx-identity{grid-column:1;grid-row:1}
  .tx-amount{grid-column:2;grid-row:1}
  .tx-sender{grid-column:1;grid-row:2}
  .tx-status{grid-column:2;grid-row:2}
  .tx-received{grid-column:1 / -1;grid-row:3}
  .tx-account{grid-column:1 / -1;grid-row:4}
  .tx-evidence{grid-column:1 / -1;grid-row:5;text-align:start}
  .tx-status .badge{white-space:nowrap}
  .tx-evidence-button{inline-size:100%;justify-content:center}
}

/* --- Phone width: the page around the list. The summary keeps the total and the count
   on one row with the divider between them (TD-19), and the export takes its own row. --- */
@media (max-width: 720px){
  .tx-summary{padding:var(--space-16);gap:var(--space-12) var(--space-20)}
  .tx-summary-figure{font-size:var(--text-xxl)}
  .tx-summary-count{padding-inline-start:var(--space-20)}
  .tx-summary-count strong{font-size:var(--text-xl)}
  .tx-export{flex:1 1 100%;margin-inline-start:0;justify-content:center}
  .tx-toolbar{padding:var(--space-16) var(--space-16) var(--space-8);gap:var(--space-12)}
  .tx-help,.tx-scope,.tx-footer,.tx-empty{padding-inline:var(--space-16)}
  /* The prototype drops the scope line's second half on a phone; the hint that a row's id
     opens its evidence is said by every row's own button. */
  #transactions-scope-hint:not([data-news]){display:none}
  .tx-when,.tx-what{gap:var(--space-12)}
  .tx-basis{flex:1 1 100%;grid-template-columns:1fr 1fr}
  .tx-select{flex-basis:var(--size-150)}
  .tx-more{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-8);
    flex:1 1 100%;min-height:var(--size-44);font-size:var(--text-sm)}
  .tx-more[aria-expanded=true]{background:var(--color-surface-selected);border-color:var(--color-action-primary)}
  .tx-what[data-more=closed] .tx-more-filters{display:none}
  .tx-what[data-more=open] .tx-more-filters{display:flex;flex-wrap:wrap;align-items:flex-start;
    gap:var(--space-12);flex:1 1 100%;min-inline-size:0}
  .tx-clear{flex:0 0 auto}
  .tx-pager{flex:1 1 100%}
  .tx-pager button{flex:1 1 auto}
}
/* The narrowest phones: the total and the count still share one row (TD-19), with the
   gap and the divider's inset taken down a step so "54,900 บาท" and "48" fit 320. */
@media (max-width: 360px){
  .tx-summary{column-gap:var(--space-12)}
  .tx-summary-count{padding-inline-start:var(--space-12)}
}

/* --- TICKET 227: the withdrawal review of each slip ---------------------------------------
   Its own column between the slip's status and the evidence: a badge in words, why a person
   is needed, and the withdrawal's id with its batch as a link. On the row layouts below the
   table's own width it is a line of its own across the row, under the received line. */
.tx-review{min-inline-size:var(--size-150)}
.tx-review .badge{white-space:normal;block-size:auto;min-block-size:var(--space-20);padding-block:var(--space-2);line-height:var(--leading-normal)}
.tx-review-why,.tx-review-quiet{display:block;margin-block-start:var(--space-4);font-size:var(--text-xs);color:var(--color-text-secondary)}
.tx-review-link{display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2) var(--space-6);
  min-height:var(--size-28);margin-block-start:var(--space-4);margin-inline-start:calc(-1 * var(--space-8))}
.tx-review-id{font-family:var(--font-mono);overflow-wrap:anywhere}
.tx-review-batch{font-size:var(--text-xs);font-weight:var(--weight-regular);color:var(--color-text-secondary)}
@container tx-panel (max-width: 1099px){
  .tx-table-wrap td.tx-review{grid-column:1 / -1;grid-row:4;display:flex;flex-wrap:wrap;align-items:center;
    gap:var(--space-4) var(--space-8);min-inline-size:0}
  .tx-review .tx-cell-label{display:inline;font-size:var(--text-xs);font-weight:var(--weight-semibold);color:var(--color-text-caption)}
  .tx-review-why,.tx-review-quiet{display:inline;margin:0}
  .tx-review-link{margin:0}
}
@container tx-panel (max-width: 559px){
  .tx-table-wrap td.tx-review{grid-row:5}
  .tx-evidence{grid-row:6}
}

/* TICKET 241 (Q6): a slip uploaded from the withdrawal review names where it came from, in words,
   in the column a Telegram slip names its sender. */
.tx-origin{display:block;font-size:var(--text-sm);font-weight:var(--weight-medium);color:var(--color-text-primary);overflow-wrap:anywhere}

/* ===== TICKET 269 begin: the transaction list as the owner's mockup (19 ต.ค. 2569) ==========================
   The heading with "ส่งออกตามตัวกรอง" on its right; the search, the range and "ตัวกรองเพิ่มเติม" in one row (the date
   basis, the account, the sender, the status and "ล้างตัวกรอง" behind it, at every width); one line with the count,
   the total and when it was read; one card of rows in five cells; the slips no withdrawal holds under it. Every
   value is a token; a card is the mockup's panel. */
.tx-heading{align-items:flex-start}
.tx-heading>.tx-head-actions{flex:0 0 auto;margin-inline-start:auto;display:flex;flex-wrap:wrap;gap:var(--space-8)}
.tx-heading>.tx-head-actions:empty{display:none}
.tx-head-actions .tx-export{margin:0;min-height:var(--size-44)}
.tx-toolbar{padding:0;gap:var(--space-12)}
.tx-what{align-items:center;gap:var(--space-12)}
.tx-what>.tx-search-field{flex:3 1 calc(var(--size-280) + var(--size-48));min-inline-size:0}
.tx-search-box input{inline-size:100%;min-height:var(--size-44)}
.tx-what>.tx-range{flex:0 1 auto;min-inline-size:0}
.tx-what>.tx-range label,.tx-what>.tx-range [id$=-label]{position:absolute;inline-size:1px;block-size:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.tx-more{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-8);flex:0 0 auto;min-height:var(--size-44);font-size:var(--text-sm)}
.tx-more[aria-expanded=true]{background:var(--color-surface-selected);border-color:var(--color-action-primary)}
.tx-what[data-more=closed] .tx-more-filters{display:none}
.tx-what[data-more=open] .tx-more-filters{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--space-12) var(--space-16);flex:1 1 100%;min-inline-size:0;
  padding:var(--space-16);background:var(--color-surface-card);border:1px solid var(--color-border-default);border-radius:var(--radius-card)}
.tx-help{padding:0}
.tx-help:empty{display:none}
.tx-summary{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-4) var(--space-16);padding:0;background:transparent;border:0;border-radius:0;box-shadow:none}
.tx-summary-line{display:flex;align-items:baseline;flex-wrap:wrap;gap:var(--space-4) var(--space-6);margin:0;flex:1 1 auto;min-inline-size:0;
  font-size:var(--text-sm);color:var(--color-text-secondary)}
.tx-summary-count{display:inline-flex;align-items:baseline;gap:var(--space-4);padding:0;border:0;align-self:auto}
.tx-summary-count strong,.tx-summary-line .tx-summary-figure{font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--color-text-primary);
  letter-spacing:normal;line-height:var(--leading-normal)}
.tx-summary-count span{font-size:var(--text-sm)}
.tx-summary-line .tx-summary-unit{font-size:var(--text-sm)}
.tx-summary-sep{color:var(--color-text-caption)}
.tx-summary .tx-freshness[data-state=ready],.tx-summary .tx-freshness[data-state=loading]{flex:0 0 auto;margin-inline-start:auto}
.tx-summary .tx-freshness{order:0}
.tx-summary .tx-summary-note{flex:1 1 100%;font-size:var(--text-xs)}
.tx-summary .tx-export-status{order:3}
.tx-panel{border-radius:var(--radius-card-lg);box-shadow:var(--shadow-sm)}
.tx-scope{background:var(--color-surface-card);font-size:var(--text-xs)}
.tx-table-wrap th{font-size:var(--text-xs);font-weight:var(--weight-medium);color:var(--color-text-secondary)}
.tx-table-wrap th{padding:var(--space-14) var(--space-16);vertical-align:middle}
.tx-main{min-inline-size:calc(var(--size-280) - var(--size-40))}
.tx-main-top{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-10);margin-block-end:var(--space-4)}
.tx-main-top>.tx-row-when{display:inline;font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--color-text-primary)}
.tx-main-top>.tx-account{min-inline-size:0}
.tx-main .bank-account-copy{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 var(--space-8)}
.tx-main .bank-account-name{font-size:var(--text-sm);font-weight:var(--weight-semibold)}
.tx-main .bank-account-meta{font-size:var(--text-xs);color:var(--color-text-secondary)}
.tx-summary-count{flex-direction:row}
.tx-main .bank-account{gap:var(--space-8)}
#transactions-panel .tx-main .bank-icon{min-inline-size:var(--size-24);block-size:var(--size-24);border-radius:var(--radius-sm)}
#transactions-panel .tx-main .bank-mark{inline-size:var(--space-16);block-size:var(--space-16)}
.tx-main-meta{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2) var(--space-10);font-size:var(--text-xs);color:var(--color-text-secondary)}
.tx-main-meta .tx-id{min-height:var(--size-24);font-size:var(--text-xs)}
.tx-main-meta .tx-sender,.tx-main-meta .tx-received{display:inline-flex;align-items:baseline;flex-wrap:wrap;gap:var(--space-4);white-space:normal}
.tx-main-meta .tx-sender small,.tx-main-meta .tx-received small,.tx-main-meta .tx-received-day{display:inline;font-size:var(--text-xs)}
.tx-main-meta .tx-received .tx-cell-label{display:inline;font-size:var(--text-xs);color:var(--color-text-caption)}
.tx-main-meta .tx-origin{display:inline;font-size:var(--text-xs);font-weight:var(--weight-regular)}
.tx-amount-figure{font-size:var(--text-sm)}
.tx-evidence-button{min-height:var(--size-40)}
.tx-unmatched{background:var(--color-surface-card);border:1px solid var(--color-border-default);border-radius:var(--radius-card-lg);box-shadow:var(--shadow-sm);overflow:hidden}
.tx-unmatched-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--space-8) var(--space-16);
  padding:var(--space-16) var(--space-20);border-bottom:1px solid var(--color-border-default)}
.tx-unmatched-head h2{margin:0;font-size:var(--text-lg)}
.tx-unmatched-open{min-height:var(--size-40);border-color:transparent;color:var(--color-text-link);font-weight:var(--weight-medium)}
.tx-unmatched-open:hover{border-color:transparent;background:var(--color-surface-selected)}
.tx-unmatched-body{display:grid;gap:var(--space-4);padding:var(--space-16) var(--space-20)}
.tx-unmatched-body p{margin:0;max-width:none;font-size:var(--text-sm);color:var(--color-text-secondary)}
.tx-unmatched-count{color:var(--color-text-primary)}
/* The rows by the width of their own region: five cells while there is room, a grid of the same cells below it. */
@container tx-panel (max-width: 1099px){
  .tx-table-wrap tr{grid-template-columns:minmax(0,1fr) auto auto;column-gap:var(--space-16)}
  .tx-identity{grid-column:1;grid-row:1 / span 2}
  .tx-amount{grid-column:2;grid-row:1}
  .tx-status{grid-column:2;grid-row:2}
  .tx-evidence{grid-column:3;grid-row:1 / span 2}
  .tx-table-wrap td.tx-review{grid-column:1 / -1;grid-row:3}
}
@container tx-panel (min-width: 860px){
  .tx-table-wrap{overflow:auto}
  .tx-table-wrap table{display:table}
  .tx-table-wrap thead{display:table-header-group}
  .tx-table-wrap tbody{display:table-row-group}
  .tx-table-wrap tr{display:table-row}
  .tx-table-wrap td{display:table-cell;padding:var(--space-14) var(--space-16);vertical-align:middle;border-block-end:1px solid var(--color-border-subtle)}
  .tx-table-wrap td.tx-review{display:table-cell}
  .tx-review .tx-cell-label{display:none}
  .tx-review-why,.tx-review-quiet{display:block;margin-block-start:var(--space-4)}
  .tx-amount .tx-cell-label{display:none}
  .tx-status .badge,.tx-review .badge{white-space:nowrap}
}
/* A phone, as the mockup's rows: the time, the account and the slip's lines across the top; then the amount, the
   slip's status and "ดูหลักฐาน" on one line; the withdrawal review under them. */
@container tx-panel (max-width: 559px){
  .tx-table-wrap tr{grid-template-columns:minmax(0,1fr) auto auto;align-items:center;column-gap:var(--space-12);row-gap:var(--space-8)}
  .tx-identity{grid-column:1 / -1;grid-row:1}
  .tx-amount{grid-column:1;grid-row:2;text-align:end}   /* amounts keep the right edge every page gives them (ticket 189) */
  .tx-status{grid-column:2;grid-row:2}
  .tx-evidence{grid-column:3;grid-row:2;text-align:end}
  .tx-table-wrap td.tx-review{grid-column:1 / -1;grid-row:3}
  .tx-evidence-button{inline-size:auto;min-height:var(--size-40)}
}
@media (max-width: 720px){
  .tx-heading>.tx-head-actions{inline-size:100%;margin-inline-start:0}
  .tx-head-actions .tx-export{flex:0 0 auto;inline-size:auto}
  .tx-what>.tx-search-field{flex:1 1 100%}
  .tx-what>.tx-range{flex:1 1 auto}
  .tx-more{flex:0 0 auto}
}
/* ===== TICKET 269 end ===== */
/* ===== TICKET 273 begin: a slip an expense holds names its category under its state ===== */
.tx-expense{display:block;margin-block-start:var(--space-4);font-size:var(--text-xs);color:var(--color-text-secondary)}
.tx-expense-label{font-weight:var(--weight-semibold)}
.tx-expense-category{color:var(--color-text-primary)}
/* ===== TICKET 273 end ===== */

/* ===== TICKET 284 begin: a slip set apart as not this company's, on its row ================================
   The reason, who and when under the slip's state, in the hold colour that says "not counted, on purpose", and the
   person's note under it. Every value is a token. */
.tx-set-apart{display:block;margin-block-start:var(--space-4);font-size:var(--text-xs);font-weight:var(--weight-semibold);
  color:var(--color-feedback-hold-text);overflow-wrap:anywhere}
.tx-set-apart-note{display:block;margin-block-start:var(--space-4);font-size:var(--text-xs);color:var(--color-text-secondary);
  overflow-wrap:anywhere}
/* The two lines are longer than a state's word: they wrap inside the state's own column, which keeps its size, so the
   amount beside it never runs under them. */
.tx-set-apart,.tx-set-apart-note{max-inline-size:var(--size-280)}
@container tx-panel (max-width: 559px){
  .tx-set-apart,.tx-set-apart-note{max-inline-size:var(--size-150)}
}
/* ===== TICKET 284 end ===== */
