/* ── THE REPORTS ─────────────────────────────────────────────────────────────
   ONE skin for every report the app draws: receivables/payables ageing, sales,
   purchases and stock movement in Finance, and the monthly production report in
   Production. They are one page with several subjects — a filter bar, a
   headline strip, CSS graphs whose bars are links back into the filters, a
   summariser carousel and a paned table that scrolls in batches — and this file
   is the whole of what draws them.

   It was `finance_reports.css` while Finance was the only section with a
   report. The plant's monthly report is the same page about tonnes rather than
   rupees, so the skin, the partials (app/views/reports/) and their helper
   (ReportsHelper) moved to a neutral home rather than being rendered across the
   namespace under a name that had stopped being true. The one thing that did
   NOT move is the fiscal-year vocabulary — Finance::Period and friends — which
   is a finance idea whatever reads it.

   It replaced finance_aging.css, finance_sales.css, finance_purchases.css and
   finance_stock.css. Those four had grown three copies of the table pane under
   three prefixes (.arep-pane, .srep-pane, .prep-pane), each restating the same
   68vh and the same two sticky rules, and `.srep` was claimed by BOTH the sales
   report and the stock report for different things — which is how a change to
   one report could silently repaint another. There is now one prefix, `.rep`,
   and a report's own specifics live at the bottom of this file under
   `.rep--<name>` where they can be seen next to everything they differ from.

   Every page also carries `.pwrap`, the party pages' component set
   (tally_parties.css): the masthead and its tiles, the section headings, the
   register table, the chips, the empty state. Those are drawn once, there, and
   are deliberately not restated here.

   No colour is spelled out that is not one of the palette variables at the end
   of layout.css; the tints are those same colours at low alpha, as everywhere
   else. There is no charting library anywhere in this app and no CDN to fetch
   one from — the plant sits behind a tunnel with no general outbound web
   access — so every graph here is bars laid out in CSS. */

/* ── the graphs, side by side where there is room ── */
.rep .rep-charts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 0.4rem 2.4rem; align-items: start;
}
.rep .rep-chart { min-width: 0; }

/* A bar is a LINK that sets a filter. It has to read as a ROW, not as a link:
   the underline and the link colour come off, and the whole row lights up on
   hover so the target is obviously the band and not the word inside it. */
.rep .rep-band {
  color: inherit; text-decoration: none; border-radius: 8px;
  transition: background 0.12s ease;
}
.rep .rep-band:hover { background: var(--rail); }
.rep .rep-band.on { background: var(--well); }
.rep .rep-band.on .bval { color: var(--ink); font-weight: 600; }

/* ── the horizontal bar chart ──
   One shape for the age ladder, the book scoreboard and the heaviest items,
   which were three different grids across three stylesheets. The name column is
   capped rather than fixed so a chip, a book nickname and a stock item name all
   sit in it without three sets of numbers. */
.rep .rep-bars { display: flex; flex-direction: column; gap: 0.4rem; }
.rep .rep-bar {
  display: grid; grid-template-columns: minmax(0, 150px) 1fr 118px;
  gap: 0.8rem; align-items: center; padding: 0.25rem 0.45rem; margin: 0 -0.45rem;
}
.rep .rep-bar-name {
  font-size: 0.8rem; font-weight: 600; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* A second figure about the row — how many bills a buyer's month came to —
   in a column of its own. It cannot ride inside the name: the name is the
   column that gets cut, so a count carried there would vanish on exactly the
   rows whose names are longest. */
.rep .rep-bar--counted { grid-template-columns: minmax(0, 150px) 2.2rem 1fr 118px; }
.rep .rep-bar-count {
  font-family: var(--party-mono); font-variant-numeric: tabular-nums;
  font-size: 0.72rem; color: var(--ink-4); text-align: right;
}
.rep .rep-bar-track { height: 8px; background: var(--edge); border-radius: 4px; overflow: hidden; }
.rep .rep-bar-track span { display: block; height: 100%; border-radius: 4px; background: var(--green); }
.rep .rep-bar .bval {
  font-size: 0.76rem; text-align: right; color: var(--ink-3);
  font-family: var(--party-mono); font-variant-numeric: tabular-nums;
}

/* The five-step age ladder — green (fresh) through gold to rust (old). The
   chips themselves are the party set's `.bkt`; these are the bar fills. */
.rep .rep-bar-track span.b0 { background: var(--green); }
.rep .rep-bar-track span.b1 { background: var(--gold); }
.rep .rep-bar-track span.b2 { background: var(--gold-ink); }
.rep .rep-bar-track span.b3 { background: var(--rust); }
.rep .rep-bar-track span.b4 { background: var(--rust-ink); }

/* ── the month graph ──
   ONE financial year on screen, April to March, with a select in the graph's
   own header that swaps the year — the party profile's flow chart, generalised
   (reports/_trend). It replaced two segmented axes: sales laid every
   year the period touched side by side under a horizontal scroll, purchases
   stacked them with a rule between each. Neither was asked for, and the owner
   read both as a line break in the middle of a graph.

   Because the axis is always twelve columns, it needs no scroll, no groups and
   no rules between anything — and April is always where April is. */
.rep .trend-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem 0.9rem;
}
.rep .trend-head h2.sect { margin-bottom: 0.2rem; }
.rep .trend-year { margin-left: auto; }
.rep .trend-year__pick {
  font-family: var(--party-mono); font-size: 0.72rem; width: auto;
  padding: 0.2rem 1.9rem 0.2rem 0.6rem; border: 1px solid var(--edge-2);
  border-radius: 999px;
  /* background-COLOR, never the shorthand: the shorthand erases
     .form-select's caret image and the control stops reading as a dropdown. */
  background-color: var(--well); color: var(--ink);
}
.rep .trend-year__pick:focus {
  outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(47, 107, 63, 0.15);
}

/* THE HEIGHT ON THE TRACK IS LOAD-BEARING. Each bar's height is a percentage,
   and a percentage height only resolves against a parent whose own height is
   definite — so `.trendbars` is given a fixed one, its columns stretch to it
   (the grid default, deliberately not overridden), and the middle `1fr` row of
   each column is what the bar then measures itself against. Swap that height
   for a min-height and every bar silently collapses to its minimum. */
.rep .trendbars {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(2.1rem, 1fr);
  gap: 0.25rem; height: 210px; padding-bottom: 0.2rem;
}
.rep .trendcol {
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 0.3rem;
  justify-items: center; height: 100%; min-width: 0; padding: 0.15rem 0.1rem;
}
/* A month the period does not reach. The columns stay — the year is the axis,
   and a year with three of its months missing is not a year — but they recede,
   and the caption over them says why in one line. */
.rep .trendcol.off { opacity: 0.38; }

.rep .trendbar {
  display: flex; align-items: flex-end; justify-content: center; gap: 2px;
  width: 100%; height: 100%; border-bottom: 1px solid var(--edge);
}
/* The fill is the LINK, so the target is the bar and not the six-character
   month under it. A month with nothing in it keeps a hairline rather than
   vanishing and closing the gap between its neighbours. */
.rep .trendfill {
  display: block; flex: 1 1 auto; max-width: 2rem; min-height: 2px;
  border-radius: 4px 4px 0 0; background: var(--green); align-self: flex-end;
}
.rep .trendfill.on { background: var(--gold); }

/* The figure over the column and the month under it, both turned on their side:
   a column is two centimetres wide and "129.8 Cr" laid flat is four. The figure
   is already abbreviated (report_short_money) so that rotating it costs about
   forty pixels of the two hundred rather than a hundred. */
.rep .trendval, .rep .trendkey {
  font-family: var(--party-mono); font-size: 0.62rem; white-space: nowrap;
  writing-mode: vertical-rl; transform: rotate(180deg);
}
.rep .trendval { color: var(--ink-4); }
.rep .trendkey { color: var(--ink-3); }

/* ── the quiet line that says what is counted ──
   Every report has one rule the reader cannot otherwise see — what counts as a
   sale, which voucher families were read as going which way — and a report that
   does not state what it counted is a report nobody can tie back to Tally.
   Boxed, so it reads as a caption for the whole page rather than a warning
   about it. It was three different things called three different names. */
.rep .rep-note {
  font-family: var(--party-mono); font-size: 0.7rem; line-height: 1.6; color: var(--ink-3);
  background: var(--rail); border: 1px solid var(--edge); border-left: 3px solid var(--green);
  border-radius: 8px; padding: 0.5rem 0.8rem; margin: 0 0 1rem; max-width: 108ch;
}
.rep .rep-note b { color: var(--ink-2); font-weight: 600; }
.rep .rep-note i { font-style: normal; color: var(--green-ink); }

/* ── what the period resolved to ──
   Under the headline tiles rather than in the filter bar, on the two reports
   whose year select can change what a word means: the bar sits outside the
   frame and would have gone stale (reports/_period says why). */
.rep .rep-range {
  font-family: var(--party-mono); font-size: 0.7rem; color: var(--ink-3);
  margin: -0.6rem 0 1.1rem;
}
.rep .rep-range b { color: var(--gold-ink); font-weight: 600; }

/* ── the three perspectives ──
   A tab is a GRAIN, not a filter — who bought, what was on the bills, which
   division it belongs to — so it sits under the totals it does not change,
   and it is drawn as a segmented control rather than as a folder tab: these
   are three readings of one answer, not three pages. */
.rep .rep-tabs {
  display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0 0 1.2rem;
  border-bottom: 1px solid var(--edge); padding-bottom: 0.5rem;
}
.rep .rep-tab {
  display: flex; flex-direction: column; gap: 0.1rem; text-decoration: none;
  padding: 0.42rem 0.9rem; border-radius: 9px; border: 1px solid transparent;
  color: var(--ink-3); background: transparent;
}
.rep .rep-tab:hover { background: var(--rail); color: var(--ink); }
.rep .rep-tab.on {
  background: var(--ink); border-color: var(--ink); color: var(--deck);
}
.rep .rep-tab-name { font-size: 0.82rem; font-weight: 600; letter-spacing: 0.01em; }
.rep .rep-tab-note {
  font-family: var(--party-mono); font-size: 0.64rem; color: var(--ink-4);
}
.rep .rep-tab.on .rep-tab-note { color: var(--deck); opacity: 0.72; }

/* ── the masters' tree, as a table ──
   Group rows carry the weight, children are indented under them and never
   sortable away from their parents (reports/_tree says why). A BUCKET
   is not a division and must not read as one: the gold rule is the office's
   mapping backlog, which on the purchases side is the biggest row on screen. */
.rep .rep-tree-group td { border-top: 1px solid var(--edge); }
.rep .rep-tree-group td b { color: var(--ink); font-weight: 600; }
.rep .rep-tree-child td { color: var(--ink-3); }
.rep .rep-tree-child .rep-tree-in { padding-left: 1.4rem; display: inline-block; }
.rep .rep-tree-child .sub {
  display: block; padding-left: 1.4rem; font-family: var(--party-mono);
  font-size: 0.64rem; color: var(--ink-4);
}
.rep .rep-bucket td { background: color-mix(in srgb, var(--gold) 9%, transparent); }
.rep .rep-bucket td:first-child { box-shadow: inset 3px 0 0 var(--gold); }

/* A bar that names a cut the page carries no filter for is read, not pressed:
   no pointer, no hover lift, and it never claims to be a band. */
.rep .rep-bar--flat { cursor: default; }

/* ── the summariser ── */
.rep .summary {
  background: var(--panel); border: 1px solid var(--edge-2); border-radius: 14px;
  padding: 0.9rem 1.1rem 1rem; margin: 1.4rem 0;
}
.rep .summary-head { display: flex; flex-wrap: wrap; gap: 0.5rem 0.9rem; align-items: center; }

/* The named tabs ARE the picker: three tabs that say what they open are worth
   more than three dots that count to three, and they replaced both the dropdown
   the older cards carried and the "2 / 10" counter beside it. */
.rep .summary-nav { margin-left: auto; display: flex; align-items: center; gap: 0.55rem; }
.rep .summary-dots { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.rep .summary-dot {
  font-family: var(--bs-font-monospace); font-size: 0.62rem; letter-spacing: 0.02em;
  padding: 0.16rem 0.5rem; border: 0; border-radius: 5px;
  background: none; color: var(--ink-4); cursor: pointer;
}
.rep .summary-dot[aria-current="true"] { background: var(--ink); color: var(--deck); }
.rep .summary-dot:hover:not([aria-current="true"]) { color: var(--ink); }

.rep .summary-arrow {
  flex: 0 0 auto; width: 2rem; border: 1px solid var(--edge-2); border-radius: 8px;
  background: var(--rail); color: var(--ink-3); font-size: 1.1rem; line-height: 1; cursor: pointer;
}
.rep .summary-arrow:hover { background: var(--well); color: var(--ink); border-color: var(--green); }

.rep .summary-stage { display: flex; align-items: stretch; gap: 0.4rem; margin-top: 0.6rem; }
.rep .summary-stage:focus-visible { outline: 2px solid var(--green); outline-offset: 4px; border-radius: 10px; }
/* The lists are different lengths — ten, ten, and however many there were. A
   floor under the tallest keeps the card from jumping under the reader's hand
   as the tabs move between them. */
.rep .summary-frame { flex: 1 1 auto; min-width: 0; min-height: 25rem; }
.rep .summary-slide[hidden] { display: none; }

/* The rule the set is ranked by, said quietly and only where a title cannot say
   it: a ranking nobody can check is a ranking nobody should act on. */
.rep .summary-rule {
  font-family: var(--party-mono); font-size: 0.66rem; color: var(--ink-4);
  margin: 0 0 0.6rem; max-width: 62ch;
}

.rep .summary-table { width: 100%; border-collapse: collapse; }
.rep .summary-table th {
  font-family: var(--party-mono); font-size: 0.64rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--ink-4); text-align: left;
  padding: 0.3rem 0.6rem; border-bottom: 1px solid var(--edge-2); white-space: nowrap;
}
.rep .summary-table td {
  font-size: 0.83rem; padding: 0.32rem 0.6rem; border-bottom: 1px solid var(--edge);
  vertical-align: baseline;
}
.rep .summary-table tbody tr:last-child td { border-bottom: 0; }
.rep .summary-table th.num, .rep .summary-table td.num { text-align: right; }
.rep .summary-table .rankcol { width: 2.2rem; }
.rep .summary-table td.rank {
  font-family: var(--party-mono); font-size: 0.8rem; font-weight: 700; color: var(--edge-2);
  font-variant-numeric: tabular-nums;
}
.rep .summary-table td.who { font-weight: 600; overflow-wrap: anywhere; }
.rep .summary-table td.who a { color: var(--green-ink); text-decoration: none; }
.rep .summary-table td.who a:hover { text-decoration: underline; }
.rep .summary-table td.fig { font-weight: 600; white-space: nowrap; }
/* the counted quantities, in the mono face the other measured figures wear */
.rep .summary-table td.count,
.rep .summary-table td.avgage,
.rep .summary-table td.qty {
  font-family: var(--party-mono); font-size: 0.74rem; color: var(--ink-3);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.rep .summary-table td.sub {
  font-family: var(--party-mono); font-size: 0.68rem; color: var(--ink-3);
}
.rep .summary-table td .bkt { margin-left: 0.4rem; vertical-align: middle; }

/* ── THE TABLE PANE — the one copy ──
   This was three: `.arep-pane` wrapping the register's `.vd-scroll`, and
   `.srep-pane` and `.prep-pane` each restating `max-height: 68vh; overflow:
   auto` and both sticky rules for themselves. One of them could be changed
   without the others and nobody would notice until two reports scrolled
   differently.

   The ceiling and the overflow are the register's own `.vd-scroll`
   (tally_browse.css) — reused rather than restated, so the panes cannot drift
   to different heights — and only the frame around it is written here. That
   class is also voucher-display's `scroll` target, which is what makes the pane
   the IntersectionObserver's ROOT; with the viewport as root a sentinel below
   the fold of an inner scroller never intersects and the list stops at fifty.

   Sticky wants a solid background or the rows scroll THROUGH it, and `border`
   does not travel with a sticky cell, so the rules are drawn with box-shadow. */
.rep .rep-pane {
  border: 1px solid var(--edge); border-radius: 12px; overflow: hidden;
  background: var(--panel); margin-top: 0.2rem;
}
.rep .rep-pane .plist { margin-top: 0; }
.rep .rep-pane thead th {
  position: sticky; top: 0; z-index: 2;
  /* the pane's stickiness must not undress .plist's dark head — panel here
     read as a pale, wrong-looking band */
  background: var(--ink); color: var(--deck);
  box-shadow: inset 0 -1px 0 var(--edge-2);
}
.rep .rep-pane tfoot td {
  position: sticky; bottom: 0; z-index: 2; background: var(--panel);
  box-shadow: inset 0 2px 0 var(--edge-2); border-top: 0;
}

/* sortable heads: the whole cell is the control, the arrow names the order */
.rep .rep-pane thead th a { color: inherit; text-decoration: none; display: inline-block; }
.rep .rep-pane thead th a:hover { text-decoration: underline; }
.rep .rep-pane thead th a.sorted::after { content: " \25B4"; font-size: 0.7em; }
.rep .rep-pane thead th a.sorted.desc::after { content: " \25BE"; }

/* ── the table itself ── */
.rep .plist { margin-top: 0.2rem; }
.rep .plist td { font-size: 0.83rem; }
.rep .plist td .bkt { margin-left: 0.4rem; }
.rep .plist td.bookcell { color: var(--ink-3); white-space: nowrap; }
.rep .plist tfoot td {
  border-top: 2px solid var(--edge-2); font-weight: 600; color: var(--ink);
  padding: 0.6rem 0.8rem; text-align: right;
}
.rep .plist tfoot td:first-child { text-align: left; }

/* The end of the batch on screen, and where the next one lands. Quiet: it is a
   place-holder for rows already on their way, not news. */
.rep .plist tr.rep-more td {
  font-family: var(--party-mono); font-size: 0.7rem; color: var(--ink-4);
  text-align: center; padding: 0.7rem 0.8rem;
}

/* An item name is not a party, so it does not take the party link's colour; it
   is still the strongest thing in its row. */
.rep .summary-table td.who.thing, .rep .plist td .pname.thing { color: var(--ink); }

/* the report that has not been drawn: an empty answer in the operator's own
   words rather than in the shape of a missing table */
.rep > .none, .rep .rep-chart > .none { margin: 1.6rem 0; }

/* ── ageing's own: collections against openings ──
   A section, not a footnote: on receivables it is ₹62.2cr, larger than several
   whole books in the table above. It reads the way the headline strip does —
   the figure first, then what it is made of — and the per-book split sits under
   it in the same table the rest of the page uses. */
.rep--aging .rep-openings {
  background: var(--panel); border: 1px solid var(--edge-2); border-radius: 14px;
  padding: 0.9rem 1.1rem 1rem; margin: 1.6rem 0 0;
}
.rep--aging .rep-openings h2.sect { margin-top: 0; }
.rep--aging .openings-figure {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.7rem;
  margin: 0.2rem 0 0.7rem;
}
.rep--aging .openings-figure .v { font-weight: 700; font-size: 1.7rem; line-height: 1; }
.rep--aging .openings-figure .note {
  font-family: var(--party-mono); font-size: 0.7rem; color: var(--ink-4);
}
.rep--aging .rep-openings .plist { margin-top: 0; }

/* ── sales' own: the two chips ──
   `unlinked` is the scope toggle's whole point made visible on the row; the
   ledger count says a name in this book was folded from more than one Tally
   ledger. An unmastered ledger's name still travels — to the voucher register —
   but it must not read as a customer page the way every other name here does. */
.rep--sales .rep-unlinked { background: rgba(168, 67, 29, 0.14); color: var(--rust-ink); }
.rep--sales .rep-ledgers  { background: rgba(146, 117, 36, 0.16); color: var(--gold-ink); }
.rep--sales .pname.unlinked { color: var(--ink-3); }

/* ── stock movement's own: the three directions ──
   Green in, rust out, and a quiet slate for the internal moves that never cross
   the gate: a transfer is the biggest tonnage on the page and the last thing
   the eye should be pulled to. This is the one report whose bars carry a colour
   that MEANS something, which is why its legend stays and the others have none. */
.rep--stock .dir-in       { color: var(--green-ink); }
.rep--stock .dir-out      { color: var(--rust-ink); }
.rep--stock .dir-transfer { color: var(--ink-3); }

.rep--stock .rep-bar-track span.dir-in,
.rep--stock .trendfill.dir-in       { background: var(--green); }
.rep--stock .rep-bar-track span.dir-out,
.rep--stock .trendfill.dir-out      { background: var(--rust); }
.rep--stock .rep-bar-track span.dir-transfer,
.rep--stock .trendfill.dir-transfer { background: var(--ink-4); }

.rep--stock .bkt.dir-in       { background: rgba(47, 107, 63, 0.14); color: var(--green-ink); }
.rep--stock .bkt.dir-out      { background: rgba(168, 67, 29, 0.16); color: var(--rust-ink); }
.rep--stock .bkt.dir-transfer { background: rgba(138, 145, 126, 0.22); color: var(--ink-2); }

/* The direction legend under the filter bar: which voucher families were read
   as going which way is a JUDGEMENT, and a judgement nobody can check is one
   nobody should act on. */
.rep--stock .rep-note { display: flex; flex-wrap: wrap; gap: 0.2rem 1.4rem; }
.rep--stock .rep-map { display: inline-flex; align-items: baseline; gap: 0.3rem; max-width: 62ch; }
.rep--stock .rep-map .dot {
  width: 0.45rem; height: 0.45rem; border-radius: 999px; flex: 0 0 auto;
  transform: translateY(-0.1rem);
}
.rep--stock .rep-map .dot.dir-in       { background: var(--green); }
.rep--stock .rep-map .dot.dir-out      { background: var(--rust); }
.rep--stock .rep-map .dot.dir-transfer { background: var(--ink-4); }

/* the voucher type beside a number, on the largest-movements list */
.rep--stock .summary-table .vtype {
  font-family: var(--party-mono); font-size: 0.66rem; color: var(--ink-4);
  font-weight: 400; margin-left: 0.4rem;
}

/* ── the daily production view's own: the day walker ──
   A section whose root is a DATE needs one control the four finance reports
   have never needed — a way to step to the day before and the day after. It
   sits inside the report frame rather than in the filter bar, because where it
   GOES changes every time the day does and the bar is never re-rendered
   (reports/_shell). Same reasoning that took the resolved date range out of the
   finance bars and put it under their headlines. */
.rep--production-day .rep-day { margin: 0 0 1.1rem; }

.rep--production-day .rep-day-walk {
  display: flex; align-items: baseline; justify-content: center;
  flex-wrap: wrap; gap: 0.4rem 1rem;
}

.rep--production-day .rep-day-name {
  font-size: 1.15rem; font-weight: 700; color: var(--ink);
  margin: 0; order: 0; flex: 1 1 auto; text-align: center;
}

.rep--production-day .rep-day-step {
  font-family: var(--party-mono); font-size: 0.76rem; font-weight: 600;
  color: var(--green-ink); text-decoration: none; white-space: nowrap;
  padding: 0.2rem 0.6rem; border: 1px solid var(--edge-2); border-radius: 999px;
  background: var(--rail); flex: 0 0 auto;
}
.rep--production-day .rep-day-step:hover { background: var(--well); }

/* An end of the walk is DEAD, not gone: a stepper that vanished would take the
   other one's position with it and the date would slide across the page. */
.rep--production-day .rep-day-step.off {
  color: var(--ink-4); background: transparent; border-style: dashed; cursor: default;
}

.rep--production-day .rep-day-pulse {
  margin: 0.5rem auto 0; max-width: 78ch; text-align: center;
  font-size: 0.8rem; color: var(--ink-3); line-height: 1.5;
}
.rep--production-day .rep-day-pulse b { color: var(--ink-2); font-weight: 600; }

/* the two chips the batch table hangs on a row that is missing something */
.rep--production-day .rep-uncoded  { background: rgba(168, 67, 29, 0.14); color: var(--rust-ink); }
.rep--production-day .rep-unbagged { background: rgba(146, 117, 36, 0.16); color: var(--gold-ink); }

/* ── the monthly production report's own: the unmapped chip ──
   `org.sku_tally_items` reaches 82.4% of the plant's tonnage today. The rest
   are the bagging line's internal codes, and they are marked rather than
   quietly listed as if they were products the office had answered for. */
.rep--production .rep-unmapped { background: rgba(107, 51, 87, 0.16); color: #552845; }
.rep--production .pname.unmapped { color: var(--ink-3); }

/* The MIS box's own crash reports, worn by the row they landed on. It writes a
   PHP warning into production_formula_name on one dispatch row in seven; the
   cell names that rather than printing the stack trace or blanking as if no
   formula had been recorded. */
.rep--production-day .rep-source-error { background: rgba(168, 67, 29, 0.14); color: var(--rust-ink); }

/* ── the period report's own: a trend whose axis is the window ──
   The month graphs draw twelve columns and get 2.1rem slots; the period
   report's day-by-day draws up to sixty-two, so its columns narrow and its
   row shortens to keep the whole window on one line. Past sixty-two days the
   partial regrains to months by itself — these rules only make the day grain
   fit, they never decide the grain. */
.rep .rep-daytrend { margin-bottom: 1.4rem; }
.rep .rep-daytrend .trendbars { grid-auto-columns: minmax(1.4rem, 1fr); height: 180px; }
.rep .rep-daytrend .trendval { font-size: 0.56rem; }

/* The line chart's longest name is a sentence about the record — "Unit-1 ·
   line not recorded" — and the shared 150px cap cuts it mid-fact. The page's
   names are few and short otherwise, so its bars get the room the sentence
   needs rather than an abbreviation nobody says. */
.rep--production .rep-bar { grid-template-columns: minmax(0, 190px) 1fr 118px; }

/* ── Which cut of a report is being read ──
   Sits with the other filters and reads as one: the office keeps several
   groupings per report, and this is which of them the figures are over. */
/* Beside the title, not among the filters: this decides WHICH population, and
   the bar below decides how it is cut. */
.rep-grouping { display: flex; align-items: center; gap: 0.5rem; }
.rep-grouping__k {
  font-size: 0.66rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-4); margin: 0;
}
.rep-grouping .form-select { width: auto; min-width: 12rem; max-width: 18rem; }
