﻿/* ==========================================================================
   Reports
   Shared by every report screen. A report is a table with a question at the
   top of it, so almost everything here is about making one figure stand out
   from the forty beside it.
   ========================================================================== */

/* --- the figures worth reading before the table -------------------------- */

/* Sits between the toolbar and the rows. Not stat tiles on a grid: these
   belong to the table under them, and a gap wide enough to float cards in
   would break the two apart. */
.age-summary {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-6);
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}

.age-summary__stat { display: flex; flex-direction: column; gap: 2px; min-width: 120px; }

.age-summary__label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--txt-3);
}

.age-summary__value { font-size: var(--fs-lg); font-weight: var(--fw-bold); }

.age-summary__note { font-size: var(--fs-xs); color: var(--txt-3); }

/* The overdue figure is the one the report exists for. */
.age-summary__stat--warn .age-summary__value { color: var(--warn-fg); }

/* What a report has to say in words, under the figures: which rule it was
   built with, or where it disagrees with the books. A flush card has no
   padding of its own, so a bare paragraph dropped in here runs to both edges
   and sits out past the table under it. */
.rep-caveat {
  margin: 0;
  padding: 10px 18px;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-xs);
  color: var(--txt-3);
}

.rep-caveat--warn { color: var(--warn-fg); }

/* --- the rows ------------------------------------------------------------ */

/* Money past its date. Amber rather than red: it is a fact about a date, not
   an error, and a column of red figures stops being read by the second week. */
.age-late { color: var(--warn-fg); font-weight: var(--fw-semibold); }

.age-total { font-weight: var(--fw-semibold); }

/* The customer's name opens their bills rather than going anywhere, so it is
   a button that reads as the link it behaves like. */
.age-row__open { text-align: left; }

/* --- a group of rows under its own heading ------------------------------- */

/* The warehouse or the category, with its total on the right. Set on the
   quieter surface so it reads as a band across the table rather than as one
   more product in it. */
.val-group th,
.val-group td {
  padding-top: 12px;
  background: var(--surface-2);
  font-weight: var(--fw-semibold);
  border-bottom: 1px solid var(--line);
}

/* The band's heading is a header cell, and the table's padding is written for
   its data cells. Left to the browser it had a pixel either side and a pixel
   under it, which set the name thirteen pixels to the left of the column it
   heads and its second line on the rule below. */
.val-group th { padding: 12px 14px 11px; text-align: left; }

/* An area of a warehouse, under the warehouse's own band: the same band one
   step quieter, with no fill and set in, so the warehouse still reads as the
   heading over its areas. */
.val-group--area th,
.val-group--area td {
  padding-top: 10px;
  background: none;
  font-weight: var(--fw-medium);
}

.val-group--area th { padding-left: 28px; }

/* --- the bills behind a row ---------------------------------------------- */

/* A table inside a cell of another table. Set on the quieter surface, inside
   the cell's own padding, so it reads as part of the row above it rather than
   as the start of a new list. (An indent was declared here for a long time
   and never applied: the table's own rule for a cell is more specific. What
   has always been on screen is the cell's padding, and that is what is kept.) */
.age-bills > td { background: var(--surface-2); }

.table--inner { width: 100%; font-size: var(--fs-sm); }

.table--inner thead th {
  padding: 8px 10px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--txt-3);
  text-align: left;
  border-bottom: 1px solid var(--line);
}

.table--inner thead th.cell-amount { text-align: right; }

.table--inner tbody td { padding: 8px 10px; border-bottom: 1px solid var(--line-2); }
.table--inner tbody tr:last-child td { border-bottom: 0; }

/* --- the index ----------------------------------------------------------- */

/* Ten cards rather than five, so they flow to as many columns as the page
   has room for instead of the dashboard's fixed thirds. On a tablet thirds
   had already collapsed to one column, which made ten cards a list fifteen
   hundred pixels long. */
.rep-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: clamp(12px, 1.4vw, 18px);
}

.rep-grid .slot { min-height: 156px; }

/* What kind of report it is, under what it says. Quiet, because it is the
   same word the chips above already offer and only needs to be findable. */
.slot__tag {
  margin-top: 10px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--surface-3);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  color: var(--txt-3);
}

/* The same list cut by what it is about, under the search box. */
.rep-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 12px 16px;
}

.rep-chip {
  min-height: 32px;
  padding: 5px 13px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--txt-2);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}

.rep-chip:hover { border-color: var(--primary); color: var(--txt); }
.rep-chip:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.rep-chip.is-on {
  border-color: transparent;
  background: var(--primary-soft);
  color: var(--primary-soft-fg);
}

.empty__text + .btn { margin-top: var(--sp-4); }

/* --- the statement and the registers -------------------------------------- */

/* The customer picker in a toolbar. A combo box is as narrow as its container
   lets it be, and beside two date boxes that was too narrow to read a name. */
.stm-pick { flex: 1 1 260px; max-width: 420px; margin-bottom: 0; }

/* The balance carried into the period: the first row, and not a document. */
.stm-carry td { color: var(--txt-3); }

/* What a quotation became, why it was turned down, or until when it is
   good: a line of its own under the outcome, because a reason is a sentence. */
.qcv-detail { display: block; margin-top: 3px; font-size: var(--fs-xs); color: var(--txt-3); }

/* The trading summary's statement: a line and a figure, two columns that fit
   a phone as they are, so it is never stacked. The expense heads stand in
   under the line they add up to, and each total is ruled off above. */
.tps-statement th,
.tps-statement td { padding: 9px 18px; border-top: 1px solid var(--line-soft); }
.tps-statement tr:first-child th,
.tps-statement tr:first-child td { border-top: 0; }
.tps-statement th { text-align: left; font-weight: var(--fw-regular); color: var(--txt); }
.tps-statement .tps-head th { padding-left: 34px; color: var(--txt-2); }
.tps-statement .tps-head td { color: var(--txt-2); }
.tps-statement .tps-total th,
.tps-statement .tps-total td { border-top: 1px solid var(--line); font-weight: var(--fw-semibold); }
.tps-note { display: block; font-size: var(--fs-xs); font-weight: var(--fw-regular); color: var(--txt-3); }

/* A month with nothing in it, said once across the row. Quiet, and set from
   the left like a sentence rather than hung off the right like a figure. */
.tps-quiet__note { color: var(--txt-3); font-size: var(--fs-sm); text-align: left; }

/* A number that was used and given up: removed, or superseded. Listed so the
   series is accounted for, and set back because nothing was supplied on it. */
.reg-void td { color: var(--txt-3); }
.reg-void .person__name { text-decoration: line-through; text-decoration-thickness: 1px; }

/* --- a table of many figures ---------------------------------------------- */

/* Nine, ten and eleven columns: the registers and the stock movement. At the
   house padding of 14px a side they come to more than a laptop is wide beside
   the rail, and the column that slides out of sight is the last one, which is
   the total. Three things make the room. None of it applies below the
   stacking width, where there are no columns left to fit.

   Scoped to the table's own rows with child combinators: the movements that
   open under a product are a table inside one of these cells, and a
   descendant selector reaches into it and flattens the indent that says whose
   rows they are.

   Over 760, here and in every block below, rather than from 761 up. A table
   stacks at 760 and under, and the width is the room inside the page's
   padding, which is seldom a whole number: at 760.5 the table had stopped
   being stacked and none of this had begun, so the figures folded under
   others were not shown anywhere. */
@container content (width > 760px) {
  /* One: tighter between the figures and quieter in the headings. */
  .table--dense > thead > tr > th,
  .table--dense > tbody > tr:not(.age-bills) > td,
  .table--dense > tfoot > tr > th,
  .table--dense > tfoot > tr > td { padding-left: 7px; padding-right: 7px; }

  .table--dense > thead > tr > th { letter-spacing: .05em; }

  .table--dense > thead > tr > th:first-child,
  .table--dense > tbody > tr:not(.age-bills) > td:first-child,
  .table--dense > tfoot > tr > th:first-child { padding-left: 14px; }

  .table--dense > thead > tr > th:last-child,
  .table--dense > tbody > tr:not(.age-bills) > td:last-child,
  .table--dense > tfoot > tr > td:last-child { padding-right: 14px; }

  /* A cell here can be two figures deep, so the rows are hung from their
     first line instead of centred: centred, a taxable value with charges
     under it sat half a line above the tax beside it and the row stopped
     reading as a row. */
  .table--dense > thead > tr > th,
  .table--dense > tbody > tr:not(.age-bills) > td,
  .table--dense > tfoot > tr > th,
  .table--dense > tfoot > tr > td { vertical-align: baseline; }

  /* Two: the name gives way before a figure does. It asks for a quarter of
     the table and takes less when the figures need the room, down to a floor,
     with the end of a long name cut off rather than the total. The zero
     maximum is what lets it: a cell cannot be made narrower than its content
     unless it is told the content does not count. The floor is a GSTIN wide,
     which is the one thing under a name that must not be cut. */
  .table--dense > thead > tr > .col-party,
  .table--dense > tbody > tr > .col-party,
  .table--dense > tfoot > tr > .col-party { width: 24%; min-width: 120px; max-width: 0; }
}

/* The narrowest a table can be and still be a table: a small laptop window,
   or a large tablet held upright. A size down and tighter again, which is the
   difference between a month of purchases fitting and its last column being
   something to scroll to. */
@container content (width > 760px) and (width <= 900px) {
  .table--dense > thead > tr > th,
  .table--dense > tbody > tr:not(.age-bills) > td,
  .table--dense > tfoot > tr > th,
  .table--dense > tfoot > tr > td { padding-left: 5px; padding-right: 5px; }

  .table--dense > thead > tr > th:first-child,
  .table--dense > tbody > tr:not(.age-bills) > td:first-child,
  .table--dense > tbody > tr.val-group > th:first-child,
  .table--dense > tfoot > tr > th:first-child { padding-left: 12px; }

  .table--dense > thead > tr > th:last-child,
  .table--dense > tbody > tr:not(.age-bills) > td:last-child,
  .table--dense > tfoot > tr > td:last-child { padding-right: 12px; }

  .table--dense > tbody > tr:not(.age-bills) > td.cell-mono,
  .table--dense > tbody > tr:not(.age-bills) > td .cell-mono,
  .table--dense > tfoot > tr > td.cell-mono { font-size: var(--fs-xs); }

  /* Still a size under the figure it is written beneath. */
  .table--dense .fold--figure { font-size: 10.5px; }
}

/* Three: a column the reader can do without at this width folds into the cell
   it belongs with instead of leaving the page. Charges go under the taxable
   value they are added to, the round off under the total it closes, the place
   of supply under the customer. The columns themselves are marked
   col-secondary, which components.css drops below 1150px; wider than that they
   are columns again and on a phone they are lines again, so what stands in for
   them only shows in between. */
.fold { display: none; }

/* A whole column that only exists in between: the three small movements of
   stock, netted into one. Two classes, to beat the stacked table's own rule
   for a cell and stay hidden there. */
.table .col-fold { display: none; }

@container content (width > 760px) and (width <= 1150px) {
  .fold { display: block; }
  .table .col-fold { display: table-cell; }
}

/* Without container queries nothing stacks either, so below the width the
   secondary columns go at, the folds are always what stands in for them. */
@supports not (container-type: inline-size) {
  @media (max-width: 1330px) {
    .fold { display: block; }
    .table .col-fold { display: table-cell; }
  }
}

/* Under a figure: the same face a size down and set back, so the column still
   reads as one figure a row with a note under some of them. The weight is
   reset because the total it sits under is bold and its round off is not a
   total. */
.fold--figure { font-size: var(--fs-xs); font-weight: var(--fw-regular); color: var(--txt-3); }

/* Under a heading: names the small figure in the cells below it, in the same
   place. Lower case and lighter, so the heading still reads as one word. */
.fold--head { font-weight: var(--fw-medium); letter-spacing: .02em; text-transform: none; }

/* A place of supply is a code and a state, and a column sized by the figures
   beside it would otherwise break it between the two. */
.reg-place { white-space: nowrap; }

/* A report whose first column is read, not glanced at.

   On a listing the name is held to 240px and cut with an ellipsis, so that
   one long customer cannot push the figures off the page, and the full name
   is a click away on the record. A report has no record to click through to:
   "Malabar Wholesale Traders Priv..." is all there is, on a table that had
   three hundred pixels to spare, and it is the same on the PDF's source.

   So here the name wraps instead. The column is given whatever the figures
   leave, a name too long for that goes onto a second line, and nothing is
   cut. Words break only where they must (break-word, not anywhere): with
   "anywhere" a table is entitled to squeeze the column to one letter wide,
   and under pressure it does.

   A dense table keeps its own width for the column (see .table--dense); what
   changes there is only that the name wraps inside it. */
.table--names .col-party { max-width: none; }

.table--names .person__name,
.table--names .person__meta,
.table--book .person__name,
.table--book .person__meta {
  white-space: normal;
  overflow: visible;
  overflow-wrap: break-word;
}

/* The production runs: a date, what was made, and five to seven figures.

   Two columns of words in one dense table, and left to itself the table gave
   the product a quarter of the width and the run what was left, which was
   92px: a date and a reference wrapped onto five lines and the row stood
   133px tall. The run is given room for a date and a reference on a line
   each, and the product gives up a little to pay for it. Only where the
   table is a table: stacked, a width on a cell would narrow the line. */
@container content (width > 760px) {
  .table--dense.table--runs > thead > tr > .col-run,
  .table--dense.table--runs > tbody > tr > .col-run,
  .table--dense.table--runs > tfoot > tr > .col-run { min-width: 150px; }

  .table--dense.table--runs > thead > tr > .col-party,
  .table--dense.table--runs > tbody > tr > .col-party,
  .table--dense.table--runs > tfoot > tr > .col-party { width: 20%; }
}

/* And at the narrowest a table still is one, the run gives some of that room
   back: a date fits in 110px, and a reference wraps under it. */
@container content (width > 760px) and (width <= 900px) {
  .table--dense.table--runs > thead > tr > .col-run,
  .table--dense.table--runs > tbody > tr > .col-run,
  .table--dense.table--runs > tfoot > tr > .col-run { min-width: 110px; }

  .table--dense.table--runs > thead > tr > .col-party,
  .table--dense.table--runs > tbody > tr > .col-party,
  .table--dense.table--runs > tfoot > tr > .col-party { width: 17%; }
}

/* A book of entries, where the particulars are the row: who was paid and what
   for, with a sentence under it. "Expense, Kerala State Electricity Board,
   factory and office, August billing" cut after the board's name says nothing
   that the amount did not. The column takes a fixed share, so that the date,
   the number and the three figures line up from one account's page to the
   next whatever the particulars happen to say.

   Only while the table is a table. Stacked on a phone the cell is a line of
   its own, and 44 per cent of that line set the particulars a word at a time:
   one row measured 643px tall, and 1,590px at 320 wide. */
.table--book .col-party { max-width: none; }

@container content (width > 760px) {
  .table--book .col-party { width: 44%; }
}

/* A line of words under a name, rather than a code. The second line is set in
   the mono face because it is nearly always a code or a number; a sentence in
   it is harder to read than it needs to be. */
.person__meta--words { font-family: inherit; }

/* An order in the open order book: a band across the table with the lines of
   the order under it.

   The band is a .val-group, which is what gives it its fill and what turns it
   into one flex line on a phone. What is added here is what goes inside it:
   who the order is from on the left, when it was promised and how it stands
   for stock beside that, and a quieter line of detail under both. It wraps
   rather than shrinks, because an order number cut short is no number. */
.ord-band__body {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 16px;
}

.ord-band__who {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  min-width: 0;
}

.ord-band__number { white-space: nowrap; }
.ord-band__customer { font-weight: var(--fw-semibold); overflow-wrap: anywhere; }

.ord-band__when {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  font-size: var(--fs-sm);
  font-weight: var(--fw-regular);
  color: var(--txt-2);
}

.ord-band__under {
  flex: 1 1 100%;
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
  color: var(--txt-3);
}

/* The amount still to deliver stays on the first line of the band, level with
   the order number, however many lines the rest of the band wraps onto. */
.ord-band > td { vertical-align: top; white-space: nowrap; }

/* A figure with a second, smaller line under it: a change and the percentage
   it comes to, a quantity and what it was last year.

   One box rather than two lines of text in the cell, because a stacked row on
   a phone is a flex line with the label on the left and the value on the
   right. Two bare lines would be two flex items, and the second would be set
   between the label and the figure instead of under the figure. */
.cell-pair {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
}

.cell-pair__under {
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
  color: var(--txt-3);
  white-space: nowrap;
}

/* The same pair in a column of words rather than figures: a date, and what
   the date does not say. Set from the left in a table. Once the row is
   stacked every value hangs off the right edge, words included, so it turns
   round there (see the container block at the foot of this file). */
.cell-pair--words { align-items: flex-start; }

/* A note that is a sentence rather than a figure is allowed to wrap. */
.cell-pair__under--wrap { white-space: normal; }

/* What a customer was sold: an item, how much, what it went out in, and the
   money. The packing is a column of words among columns of figures, and the
   only one allowed to wrap: "40 Cartons of 12 nos (2 part filled)" held on one
   line would take the room the item's own name needs.

   Only while the table is a table. Stacked on a phone the cell is a line of
   its own and a width on it would set the words in a strip down one side. */
.table--sold .col-pack { white-space: normal; }

@container content (width > 760px) {
  .table--sold > thead > tr > .col-pack,
  .table--sold > tbody > tr > .col-pack,
  .table--sold > tfoot > tr > .col-pack { width: 22%; min-width: 150px; }
}

/* Several ways one item went out, or several units in one total: a line each,
   in one box, for the reason a pair is one box. A stacked row is a flex line
   with the label on the left, and bare lines would each be set as a value of
   their own. */
.pack-ways { display: inline-flex; flex-direction: column; gap: 2px; }

/* The same thing in a column of figures, which is read from the right. */
.pack-ways--figures { align-items: flex-end; }

/* A caveat that closes a card instead of sitting under its head: ruled off
   from the table above it, with nothing under it to be ruled off from. */
.rep-caveat--foot { border-top: 1px solid var(--line); border-bottom: 0; }

/* The second line keeps the colour of a figure that is marked late or short:
   a fall of eighteen per cent in grey beside the amount in amber reads as two
   different facts. */
.age-late .cell-pair__under { color: inherit; }

/* --- a table inside a row ------------------------------------------------- */

/* The bills behind an ageing row and the movements behind a product. Seven
   columns do not fit a phone, and a table left to its own width pushed the
   whole page sideways; this scrolls on its own instead, inside the row it
   belongs to. */
.age-bills__scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.age-bills__scroll .table--inner { min-width: 520px; }
.age-bills__scroll .table--inner-wide { min-width: 680px; }

/* --- the foot ------------------------------------------------------------ */

/* The whole book, under the rows it adds up. Ruled off above rather than
   banded, so it is the last line of the table and not one more row in it. */
.table tfoot th,
.table tfoot td {
  padding: 12px 14px;
  border-top: 2px solid var(--line);
  font-weight: var(--fw-semibold);
  background: var(--surface-2);
}

/* Its label is a header cell, which a browser centres unless told otherwise.
   It stands under a column of names set from the left, and belongs on the
   same edge. */
.table tfoot th { text-align: left; }

.table tfoot td.cell-amount { text-align: right; }

@media (max-width: 860px) {
  .age-summary { gap: var(--sp-4); padding: 12px 14px; }
}

/* The foot stacks with the rows, and a label-less column of figures under them
   says nothing. It is the one row where the labels have to be drawn, so it is
   laid out exactly as a stacked row is: the caption reads as the heading, and
   every figure under it carries the column it came from.

   On the same container query the rows themselves stack under, not a width
   media query. The two have to turn over together: at 800px in a narrowed
   content area a foot that had stacked on its own would be sitting under a
   table that had not. */
@container content (max-width: 760px) {
  /* The foot has to stop being a table footer as well, or its row keeps
     shrink-to-fit sizing from an anonymous table box and every figure sits
     against its label instead of out at the right edge. */
  /* A report on a phone is read down the page, not through a window in it.
     The cap on a tall table is there to hold the column headings over the
     rows, and stacked there are no headings to hold: what was left was a box
     half a screen high showing one invoice at a time, with the totals at the
     bottom of a scroll inside a scroll. Marked rather than applied to every
     tall table: a listing that fetches its rows a window at a time needs the
     box to have a bottom, and a report is read whole. */
  .table-wrap--whole { max-height: none; }

  .cell-pair--words { align-items: flex-end; text-align: right; }

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

  /* Sixteen a side, which is what a stacked row has. At the fourteen a cell
     has on a wide screen the foot stood two pixels proud of the rows it adds
     up, on both edges. */
  .table--stack tfoot tr {
    display: block;
    border-top: 2px solid var(--line);
    padding: 10px 16px;
  }

  .table--stack tfoot th {
    display: block;
    padding: 0 0 6px;
    border-top: 0;
    background: none;
    text-align: left;
  }

  .table--stack tfoot td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 3px 0;
    border-top: 0;
    background: none;
    text-align: right;
  }

  .table--stack tfoot td::before {
    content: attr(data-label);
    flex: none;
    font-size: 10.5px;
    font-weight: var(--fw-bold);
    letter-spacing: .11em;
    text-transform: uppercase;
    color: var(--txt-3);
    text-align: left;
  }

  /* A foot cell that only holds a column open on a wide screen. Stacked there
     is no column to hold open, and an unlabelled blank line under the total
     reads as a figure somebody forgot to fill in. */
  .table--stack tfoot td:not([data-label]) { display: none; }

  /* A figure in a column the wide table had dropped comes back as a line of
     its own, the way the same column does in the rows above the foot. */
  .table--stack tfoot td.col-secondary[data-label] { display: flex; }

  /* The band over a group of rows. Stacked it is one line of its own, the
     name against its total, rather than a row of labelled fields: it is a
     heading for what follows, and it was splitting into a half-wide band with
     the figure stranded underneath. */
  .table--stack tbody tr.val-group {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    padding: 10px 16px;
  }

  .table--stack tbody tr.val-group th { padding: 0; border-bottom: 0; }

  .table--stack tbody tr.ord-band th { flex: 1 1 auto; min-width: 0; }

  /* The balance brought forward has a date, a caption and a balance, and
     nothing in the columns between. On a table those are blanks that hold the
     columns open. Stacked, each became a label with nothing beside it:
     "Reference", "Received", "Paid", three lines saying nothing above the one
     line that says something. */
  .table--stack tbody tr.stm-carry td:empty,
  .table--stack.table--stack-all tbody tr.stm-carry td:empty { display: none; }

  /* One fill for the whole band. The cells carry the fill on a wide screen,
     where they are the band between them. Stacked, the row is the band and
     the cells sit inside its padding, so a filled cell showed as a lighter
     box in a darker strip. */
  .table--stack tbody tr.val-group { background: var(--surface-2); }

  .table--stack tbody tr.val-group th,
  .table--stack.table--stack-all tbody tr.val-group td { background: none; }

  /* An area under its warehouse: the same line one step quieter, set in
     and with no fill, so the warehouse's band heads both. */
  .table--stack tbody tr.val-group--area { background: none; padding-left: 28px; }

  /* The table under an opened row stays a table.

     Everything that stacks a table is written for its descendants, and the
     table under an opened row is one: its headings were hidden with the outer
     ones, its rows became blocks two hundred pixels tall, and its values were
     set against the right edge of a 520px table in a 300px window. What was
     on screen was a column of dates.

     It is a small table of its own with its own headings, and it is put back
     together here: a real table, scrolled sideways inside its wrapper, which
     is what .age-bills__scroll has always been there to do. Each rule is
     written twice because the outer table's own rules come at two strengths,
     with and without table--stack-all, and this has to beat both. */
  .table--stack tbody tr.age-bills,
  .table--stack.table--stack-all tbody tr.age-bills { padding: 0 0 4px; }

  .table--stack tbody tr.age-bills > td,
  .table--stack.table--stack-all tbody tr.age-bills > td {
    display: block;
    position: static;
    padding: 0;
    text-align: left;
  }

  .table--stack tbody tr.age-bills > td::before,
  .table--stack.table--stack-all tbody tr.age-bills > td::before { content: none; }

  .table--stack .table--inner { display: table; }
  .table--stack .table--inner > thead { display: table-header-group; }
  .table--stack .table--inner > tbody { display: table-row-group; width: auto; }

  /* The heading row as well as the body rows. Left as a block, the browser
     wraps it in a cell of its own and puts that cell in the first column:
     the headings sit in a 600px box over the first column, and every figure
     is 600px to the right of the heading it belongs under. */
  .table--stack .table--inner > thead > tr,
  .table--stack.table--stack-all .table--inner > thead > tr { display: table-row; padding: 0; }

  .table--stack .table--inner > tbody > tr,
  .table--stack.table--stack-all .table--inner > tbody > tr {
    display: table-row;
    position: static;
    padding: 0;
  }

  /* One line a row. The table scrolls sideways here whatever is done, so
     there is nothing to gain by letting "03 Jul 2026" fold onto three lines
     to save width, and a row three lines tall shows a third as many rows. */
  .table--stack .table--inner > tbody > tr > td,
  .table--stack.table--stack-all .table--inner > tbody > tr > td {
    display: table-cell;
    position: static;
    padding: 8px 10px;
    text-align: left;
    white-space: nowrap;
  }

  .table--stack .table--inner > tbody > tr > td.cell-amount,
  .table--stack.table--stack-all .table--inner > tbody > tr > td.cell-amount { text-align: right; }

  .table--stack .table--inner > tbody > tr > td::before,
  .table--stack.table--stack-all .table--inner > tbody > tr > td::before { content: none; }

  .table--stack.table--stack-all tbody tr.val-group td {
    display: block;
    padding: 0;
    border-bottom: 0;
    text-align: right;
  }

  .table--stack.table--stack-all tbody tr.val-group td::before { content: none; }
}
