/*
 * ledger.css -- /money/ledger, the libro mayor.
 *
 * One rule shapes the whole page: the ONLY figure that gets a colour is what a
 * client still owes. Facturado and Cobrado are facts you read; Pendiente is the
 * one you act on, and colouring all three would mean none of them stands out.
 *
 * Finantzak's version used amber on near-black. This is the same information in
 * the house palette, which is paper -- so the four debt bands are carried by a
 * rust ramp rather than a neon one, and the "nothing owed" state is the green
 * already used for Paul on the members page rather than a fifth hue.
 */

/* --- the filter bar ------------------------------------------------------- */

.lm-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: center;
  margin-bottom: 14px;
}
.lm-group { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.lm-group > .micro { margin-right: 4px; }

.lm-fbtn {
  font: inherit;
  font-family: var(--mono);
  font-size: 11px;
  padding: 4px 11px;
  cursor: pointer;
  background: var(--card);
  color: var(--muted);
  border: 1px solid var(--rule);
}
.lm-fbtn:hover { color: var(--ink); border-color: var(--hairline); }
.lm-fbtn.active {
  background: var(--ink);
  color: var(--card);
  border-color: var(--ink);
}

/* --- Pendiente is the page ------------------------------------------------
 *
 * There was a band of three big figures here -- Facturado, Cobrado, Pendiente,
 * the same size as each other. It answered a question nobody opens this page to
 * ask. The page exists to show who owes money, and two other numbers set at the
 * same weight as that one is exactly how it stopped saying so.
 *
 * So the band is gone, its total moved into the foot of the Pendiente column,
 * and Pendiente is the only figure on the page with size, weight and colour.
 * Everything else is context you read after you have found the thing.
 */

.lm-owe {
  font-weight: 700;
  font-size: 15px !important;
  color: var(--alarm);
}
.lm-head .lm-owe,
.grid.lm-dept thead .lm-owe {
  font-size: 10px !important;
  font-weight: 700;
  color: var(--alarm);
}

/* Nothing owed is not the same as good -- a client with no invoices reads 0,00
   too -- so it drops back to the quiet weight rather than turning green-loud. */
.lm-owe.ok { color: var(--muted); font-weight: 400; }
.lm-owe.warn1 { color: var(--ink); }
.lm-owe.warn2 { color: #a8511b; }
.lm-owe.bad { color: var(--alarm); }

/* The sum of the column, in the foot of the column. */
.grid.lm-dept tfoot td {
  border-top: 2px solid var(--hairline);
  font-weight: 700;
  padding-top: 7px;
}
.grid.lm-dept tfoot .lm-owe { font-size: 17px !important; }
.grid.lm-dept td, .grid.lm-dept th { vertical-align: baseline; }

/* --- the client list ------------------------------------------------------ */
/*
 * The header row and every client row share one grid template, declared once.
 * Two copies of a column spec is how a header stops lining up with its body the
 * first time a width changes.
 */
.lm-row {
  display: grid;
  grid-template-columns: 1fr 104px 104px 136px;
  gap: 8px;
  align-items: baseline;
  padding: 8px 12px;
}
.lm-row .num {
  font-family: var(--mono);
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--muted-2);
}
.lm-head {
  border-bottom: 1px solid var(--hairline);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface-2);
}
.lm-head .num { font-size: 10px; }

.lm-client { border-bottom: 1px solid var(--rule); }
.lm-client:last-child { border-bottom: none; }
.lm-client > .lm-row { cursor: pointer; }
.lm-client > .lm-row:hover { background: var(--surface-2); }

.lm-name { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; min-width: 0; }
.lm-caret { font-size: 9px; color: var(--muted); width: 9px; flex: 0 0 auto; }
.lm-cli { font-size: 13px; }
/* What people actually call them, against what the invoice says. */
.lm-alias { font-size: 11px; color: var(--muted); font-style: italic; }
.lm-gap { font-size: 11px; color: var(--alarm); }
.lm-dept {
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.05em;
  padding: 1px 5px;
  border: 1px solid var(--rule);
  color: var(--muted);
}

/* The four debt bands. Green means nothing is owed -- which is not the same as
   good, since a client with no invoices also reads 0,00. */
.lm-row .num.ok { color: var(--paul); }
.lm-row .num.warn1 { color: var(--muted); }
.lm-row .num.warn2 { color: #b06a1e; }
.lm-row .num.bad { color: var(--alarm); }
.lm-fig.ok { color: var(--paul); }
.lm-fig.warn1, .lm-fig.warn2 { color: var(--ink); }
.lm-fig.bad { color: var(--alarm); }
.grid.lm-grid td.num.ok { color: var(--paul); }
.grid.lm-grid td.num.warn2 { color: #b06a1e; }
.grid.lm-grid td.num.bad { color: var(--alarm); }

/* --- a client, opened ----------------------------------------------------- */

.lm-det { padding: 2px 12px 14px 28px; background: var(--surface-2); }
.lm-sub { margin: 10px 0 5px; }
.grid.lm-grid { font-size: 12px; }
.grid.lm-grid td, .grid.lm-grid th { padding: 4px 8px; }

/* Collected, but not through a bank movement we hold -- Stripe, cash, an
   offset. Real money; a different provenance, so it is marked rather than
   silently mixed in with the bank rows. */
.lm-offbank td { font-style: italic; color: var(--muted-2); }
/* Declared collected, not yet seen in the bank. */
.lm-prov td { color: #b06a1e; }

.lm-pdf {
  font-size: 13px;
  text-decoration: none;
  opacity: 0.55;
}
.lm-pdf:hover { opacity: 1; }
.lm-nofile { color: var(--faint); }

.lm-empty { padding: 14px 12px; }
.lm-foot { margin-top: 14px; max-width: 78ch; }

/* --- the tail buckets ----------------------------------------------------- */

.lm-bucket > .lm-bhead { cursor: pointer; }
.lm-bucket > .lm-bhead:hover { background: var(--surface-2); }
.lm-bhead .num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 13px;
}
.lm-bhead .num.bad { color: var(--alarm); }

/* --- /money/reconciliation -----------------------------------------------
 *
 * A `full` route: it fills the viewport, only the two card columns scroll, and
 * the PDF keeps whatever height is left. A reconciliation screen where the page
 * itself scrolls is unusable -- you lose the document the moment you reach for
 * a movement further down the list.
 *
 * Three columns, fixed-flexible-fixed. The lists have a natural width (a date,
 * a truncated concept, an amount) and the document does not, so the document
 * takes the slack.
 */

.rc { display: flex; flex-direction: column; height: 100%; min-height: 0; }

.rc-bar {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: center;
  padding: 8px 14px; border-bottom: 1px solid var(--hairline);
  background: var(--card); flex: 0 0 auto;
}
.rc-group { display: flex; gap: 4px; align-items: center; }
.rc-period {
  font-family: var(--mono); font-size: 12px; min-width: 130px; text-align: center;
}
.rc-only {
  display: flex; align-items: center; gap: 5px;
  font-size: 11.5px; color: var(--muted); cursor: pointer;
}
.rc-counts { margin-left: auto; }

.rc-cols {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr) 340px;
  flex: 1 1 auto; min-height: 0;
  border-bottom: 1px solid var(--hairline);
}
.rc-col {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  background: var(--surface-2);
}
.rc-col:first-child { border-right: 1px solid var(--hairline); }
.rc-col:last-child { border-left: 1px solid var(--hairline); }

.rc-head {
  padding: 8px 10px; border-bottom: 1px solid var(--rule);
  display: flex; flex-direction: column; gap: 5px;
  background: var(--card); flex: 0 0 auto;
}
.rc-head .rc-group { flex-wrap: wrap; }
.rc-in {
  font: inherit; font-size: 11.5px; padding: 5px 8px; width: 100%;
  background: var(--card); color: var(--ink); border: 1px solid var(--rule);
}
.rc-in:focus { outline: none; border-color: var(--hairline); background: var(--field-focus); }
.rc-sorted { color: var(--accent-purple); }

.rc-body { flex: 1 1 auto; overflow-y: auto; padding: 7px; min-height: 0; }
.rc-none { padding: 18px 8px; text-align: center; }

/* --- a candidate --------------------------------------------------------- */

.rc-card {
  border: 1px solid var(--rule);
  background: var(--card);
  padding: 7px 9px;
  margin-bottom: 5px;
  cursor: pointer;
  font-size: 11.5px;
}
.rc-card:hover { border-color: var(--hairline); }
/* Selected is a solid left edge rather than a fill: a filled card competes
   with the amount, which is the thing being compared. */
.rc-card.on { border-color: var(--hairline); box-shadow: inset 3px 0 0 var(--paul); }
.rc-card.linked { opacity: 0.72; }

.rc-card-top { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
.rc-card-bot { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.rc-tick { font-size: 11px; color: var(--muted); }
.rc-card.on .rc-tick { color: var(--paul); }
.rc-date { font-family: var(--mono); font-size: 9.5px; color: var(--muted); }
.rc-badge {
  font-size: 9px; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent-purple); border: 1px solid currentColor; padding: 0 3px;
}
/* A card on screen only because the filter is off. Same badge, drained of
   colour: it names the state without asking anything of you. `.rc-badge`
   borders in currentColor, so the colour is the whole change. */
.rc-badge-off { color: var(--faint); }

/* The bar does not wrap, so anything in it that cannot shrink pushes the whole
   page sideways -- which is exactly what a long counts string did. This lets
   it shrink and clip instead of winning. */
.rc-counts {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rc-kind { font-size: 9px; color: var(--muted); }
.rc-kind.emitted { color: var(--paul); }
.rc-kind.received { color: #b06a1e; }
.rc-concept {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-bottom: 3px;
}
.rc-inv-num { font-family: var(--mono); font-size: 9.5px; color: var(--muted); }
.rc-amt {
  font-family: var(--mono); font-weight: 700; font-size: 12.5px;
  text-align: right; font-variant-numeric: tabular-nums;
}
.rc-amt.neg { color: var(--alarm); }
.rc-amt.pos { color: var(--paul); }

/* Confidence. Never colour alone -- the number is always written out. */
.rc-dot { margin-left: auto; font-family: var(--mono); font-size: 9px; font-weight: 700; }
.rc-dot.hi { color: var(--paul); }
.rc-dot.mid { color: #b06a1e; }
.rc-dot.lo { color: var(--faint); }

/* --- the document -------------------------------------------------------- */

.rc-pdf { display: flex; flex-direction: column; min-height: 0; background: var(--paper); }
.rc-pdfhead { flex-direction: row; align-items: center; gap: 10px; }
.rc-pdfname {
  font-family: var(--mono); font-size: 10.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto;
}
.rc-frame { flex: 1 1 auto; width: 100%; border: none; background: #fff; min-height: 0; }
.rc-empty {
  flex: 1 1 auto; display: flex; align-items: center; justify-content: center;
  padding: 24px; text-align: center;
}

/* --- what will happen when you press the button -------------------------- */

.rc-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; padding: 9px 14px; background: var(--card); flex: 0 0 auto;
  flex-wrap: wrap;
}
.rc-sel { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.rc-act { display: flex; align-items: center; gap: 10px; }

/* The two sides' totals, side by side. This is the check a person would do in
   their head, done for them -- and the reason a wrong match gets caught before
   the button rather than after. */
.rc-gap { font-family: var(--mono); font-size: 11.5px; }
.rc-gap.ok { color: var(--paul); }
.rc-gap.near { color: #b06a1e; }
.rc-gap.off { color: var(--alarm); }

.rc-existing { display: flex; flex-direction: column; gap: 3px; }
.rc-exrow { display: flex; align-items: baseline; gap: 8px; font-size: 11.5px; }


@media (max-width: 1100px) {
  /* Below this the three columns stop being three columns. The document goes
     first because it is the thing you are reading, and both lists keep their
     own scroll. */
  .rc-cols { grid-template-columns: 1fr; grid-auto-rows: minmax(220px, auto); }
  .rc-col:first-child, .rc-col:last-child { border: none; border-top: 1px solid var(--hairline); }
  .rc-pdf { order: -1; min-height: 320px; }
}

/* Odoo did not answer. Not decoration: without it a longer list reads as an
   honest backlog rather than a missing verdict. */
.rc-odoo-down { color: var(--accent-red, #9c4a3d); }

/* The approvals queue. Above the columns because it is the only part of this
   page that is waiting on a person rather than on a decision about data. */
.aq {
  flex: 0 0 auto;
  border-bottom: 1px solid var(--hairline);
  background: var(--card);
  max-height: 34vh;
  overflow-y: auto;
}
.aq-head {
  display: flex; align-items: baseline; gap: 10px;
  padding: 7px 14px 5px;
}
.aq-t { font-size: 12px; font-weight: 700; }
.aq-row {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr) auto;
  align-items: center; gap: 10px;
  padding: 5px 14px;
  border-top: 1px solid var(--hairline);
  font-size: 11.5px;
}
.aq-who { display: flex; flex-direction: column; }
.aq-by { font-weight: 700; }
.aq-pair { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.aq-m, .aq-i {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--mono); font-size: 10.5px;
}
.aq-i { color: var(--muted); }
.aq-act { display: flex; gap: 6px; }
.aq-ok, .aq-no {
  font: inherit; font-size: 11px; padding: 3px 9px; cursor: pointer;
  border: 1px solid currentColor; background: transparent;
}
.aq-ok { color: var(--paul); }
.aq-no { color: var(--muted); }
.aq-ok:hover { background: var(--paul); color: #fff; }
.aq-no:hover { background: var(--muted); color: #fff; }

/* On a phone the three figure columns fit the screen (Paul, 2026-11-05). */
@media (max-width: 600px) {
  .lm-row { grid-template-columns: minmax(0, 1fr) 76px 76px 84px; gap: 4px; padding: 8px; }
  .lm-row .num { font-size: 11px; }
  .lm-row .lm-owe { font-size: 12px !important; }
}
