:root{
  --anchor:#265D76; --blue:#006FA1; --orange:#ED7D31;
  --ink:#1c2b33; --mid:#5a6b74; --line:#d8e0e5; --bg:#f4f7f9; --white:#fff;
  --ok:#2e7d55; --warn:#b26a00; --bad:#b3261e;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{background:var(--bg);color:var(--ink);
  font-family:Montserrat,"Segoe UI",-apple-system,system-ui,Roboto,Arial,sans-serif;
  font-size:14px;line-height:1.5}
a{color:var(--blue)}
.appbar{background:var(--anchor);color:#fff;padding:11px 18px;display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.appbar .brand{font-weight:700;font-size:15px}
.appbar .brand em{font-style:normal;opacity:.65;font-weight:500}
.appbar .right{font-size:12.5px;opacity:.92;display:flex;align-items:center;gap:12px}
.appbar .right form{margin:0}
.appbar .right button{background:none;border:1px solid rgba(255,255,255,.45);color:#fff;border-radius:3px;padding:3px 10px;font:inherit;font-size:12px;cursor:pointer}
.tabs{display:flex;gap:2px;background:#1e4c60;padding:0 12px;flex-wrap:wrap}
.tabs a{color:#cfe2ea;text-decoration:none;font-size:12.5px;padding:9px 13px;border-bottom:3px solid transparent}
.tabs a.on{color:#fff;border-bottom-color:var(--orange);font-weight:600}
.tabs a:hover{color:#fff}
.wrap{max-width:1400px;margin:0 auto;padding:20px 18px 60px}
.wrap.narrow{max-width:900px}
h1{font-size:20px;color:var(--anchor);margin:0 0 4px}
h2{font-size:16px;color:var(--anchor);margin:26px 0 10px}
.lede{color:var(--mid);margin:0 0 18px;max-width:75ch}
.card{background:var(--white);border:1px solid var(--line);border-radius:6px;padding:18px;margin-bottom:18px}
.card.tight{padding:0;overflow:hidden}
.card h3{margin:0;background:#eef3f6;padding:9px 14px;font-size:11.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--mid);border-bottom:1px solid var(--line)}
.card .body{padding:14px}
.formrow{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;margin-bottom:14px}
.formrow.three{grid-template-columns:repeat(3,1fr)}
.f label{display:block;font-size:11.5px;font-weight:700;color:var(--mid);text-transform:uppercase;letter-spacing:.4px;margin-bottom:4px}
.f .req{color:var(--bad)}
/* `input:not([type])` matters more than it looks. An input with no type IS a
   text input to the browser, but it does NOT match `input[type=text]` — so a
   forgotten attribute silently drops the width, the border and the padding, and
   the field shrinks to fit its own placeholder. Fourteen inputs across this
   application were in that state. Fixing the selector fixes all of them and
   every future one, which is why this is here rather than in fourteen
   templates. */
input:not([type]),input[type=text],input[type=date],input[type=email],input[type=password],input[type=file],select,textarea{
  width:100%;border:1px solid #c3ced5;border-radius:4px;padding:9px 11px;font:inherit;font-size:13.5px;background:#fff;color:var(--ink)}
textarea{min-height:64px;resize:vertical}
input:focus,select:focus,textarea:focus{outline:2px solid var(--blue);outline-offset:-1px;border-color:var(--blue)}
.hint{font-size:11.5px;color:var(--mid);margin-top:5px}
.btn{display:inline-block;background:var(--orange);color:#fff;border:none;border-radius:4px;padding:10px 20px;font:inherit;font-weight:700;font-size:13.5px;cursor:pointer;text-decoration:none}
.btn:hover{filter:brightness(.94)}
.btn.blue{background:var(--blue)}
.btn.ghost{background:#fff;color:var(--anchor);border:1px solid var(--anchor);font-weight:600}
.btn:disabled{opacity:.5;cursor:not-allowed}
.msg{padding:11px 14px;border-radius:4px;font-size:13px;margin-bottom:16px}
.msg.ok{background:#eef8f2;border-left:3px solid var(--ok);color:#1f6344}
.msg.warn{background:#fff8ef;border-left:3px solid var(--orange);color:#8a4d10}
.msg.bad{background:#fdf1ef;border-left:3px solid var(--bad);color:#8f231a}
.note{background:#fff8ef;border-left:3px solid var(--orange);padding:10px 13px;font-size:12.5px;margin:14px 0;color:#6b4a22}
table.grid{width:100%;border-collapse:collapse;font-size:12.5px;background:#fff}
table.grid th{background:#eef3f6;text-align:left;padding:8px 10px;font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--mid);border-bottom:1px solid var(--line);white-space:nowrap}
table.grid td{padding:9px 10px;border-bottom:1px solid #eef2f4;vertical-align:middle}
table.grid tbody tr:hover td{background:#f7fbfc}
table.grid td a{text-decoration:none;font-weight:600}
.num{text-align:right;font-variant-numeric:tabular-nums;font-family:ui-monospace,Consolas,monospace;white-space:nowrap}
.neg{color:var(--bad);font-weight:700}
.zero{color:var(--ok)}
.pill{display:inline-block;font-size:10.5px;font-weight:700;padding:2px 8px;border-radius:10px;white-space:nowrap}
.s-variance_open{background:#fbe9e7;color:#a3271c}
.s-reconciled{background:#e3f2ea;color:#1f6344}
.s-resolved{background:#e9eef1;color:#3d5058}
.s-awaiting_remit{background:#fdf0e6;color:#a2560f}
.s-ready_to_post{background:#e7f2f8;color:#0b5b7d}
/* Deliberately grey and quiet. Not ours to post is not an outcome to celebrate
   or an alarm to raise — it is a row that stopped being a question. */
.s-excluded{background:#eceff1;color:#546067}
.s-awaiting_deposit{background:#f3eefb;color:#5a3d8a}
/* A bank line that was divided between payers. Its own colour, because it is
   not a payment and must not read as one: the parts carry the money. */
.s-split{background:#e6eef7;color:#2c4a70}
/* The bank line as it appears in the queue, which it only does while its parts
   do not add up. Marked in the table itself, not only by its pill — a row of
   figures that belong to four other rows should not look like an ordinary one. */
table.grid tr.bankline td{background:#f4f7fb}
table.grid tr.bankline:hover td{background:#eef3fa}
.bankline-note{font-size:11.5px;color:var(--mid);margin-top:2px}
.bankline-note b{color:var(--bad)}
.own{font-weight:700;font-size:11.5px}
.own-Client{color:var(--blue)} .own-RCS{color:var(--orange)}
.age{font-weight:700;font-variant-numeric:tabular-nums}
.age.hot{color:var(--bad)} .age.warm{color:var(--warn)}
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:16px}
.kpi{background:#fff;border:1px solid var(--line);border-radius:5px;padding:12px 14px}
.kpi .lbl{font-size:10.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--mid);font-weight:700}
.kpi .val{font-size:23px;font-weight:700;margin-top:3px;font-variant-numeric:tabular-nums}
.kpi .val.bad{color:var(--bad)} .kpi .val.ok{color:var(--ok)}
.kpi .sub{font-size:11px;color:var(--mid);margin-top:1px}
.filters{display:flex;gap:8px;flex-wrap:wrap;align-items:flex-end;margin-bottom:14px;background:#fff;border:1px solid var(--line);border-radius:5px;padding:12px}
.filters .f{min-width:130px}
.filters .f.grow{flex:1;min-width:220px}
.filters select,.filters input{padding:7px 9px;font-size:12.5px}
.split{display:grid;grid-template-columns:1.5fr 1fr;gap:18px;align-items:start}
/* Grid items default to min-width:auto, which means they refuse to shrink below
   their content. A wide spreadsheet in the left pane therefore pushed the right
   one into a strip and crushed the entry form — defeating the split screen the
   whole layout exists for. min-width:0 lets the column hold its 1.5fr share and
   makes the table scroll inside it instead. */
.split > *{min-width:0}
.kv{display:grid;grid-template-columns:140px 1fr;gap:6px 10px;font-size:12.5px;margin:0}
.kv dt{color:var(--mid)} .kv dd{margin:0;font-weight:600}
.hist{font-size:12.5px;color:var(--mid);line-height:1.7}
.hist b{color:var(--ink)}
.bar{height:9px;background:#eef2f4;border-radius:5px;overflow:hidden;margin-top:4px;min-width:60px}
.bar i{display:block;height:100%;background:var(--blue)}
.signin{max-width:400px;margin:70px auto;background:#fff;border:1px solid var(--line);border-radius:7px;padding:26px}
.signin h1{margin-bottom:14px}
.muted{color:var(--mid);font-size:12px}
.right{text-align:right}
.pastegrid{width:100%;border-collapse:collapse;font-size:12.5px}
.pastegrid th{background:#eef3f6;padding:7px 8px;font-size:10.5px;text-transform:uppercase;letter-spacing:.4px;color:var(--mid);text-align:left}
.pastegrid td{padding:5px 8px;border-bottom:1px solid #eef2f4}
.pastegrid input,.pastegrid select{padding:5px 7px;font-size:12.5px}
.pastegrid tr.skip{opacity:.4}
.pastegrid tr.bad td{background:#fdf1ef}
@media(max-width:900px){.split,.formrow,.formrow.three{grid-template-columns:1fr}}

/* Floating help button. Every internal tool has one in the same place, so
   "where is the guide" is never a question. */
.helpbtn {
  position: fixed; right: 20px; bottom: 20px; z-index: 50;
  width: 42px; height: 42px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: #0f766e; color: #fff; text-decoration: none;
  font: 700 20px/1 system-ui, sans-serif;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .25);
}
.helpbtn:hover { background: #115e59; }
@media print { .helpbtn { display: none; } }

/* Branding. The canonical RCS marks, copied from the Team Vault brand folder —
   the white lockup on the dark app bar, the black one on white pages that are
   reached before the app bar exists (sign-in, invitation). */
.appbar .brand{display:flex;align-items:center;gap:11px}
.brand__mark{height:26px;width:auto;display:block}
/* The round mark reads smaller than the wordmark at the same height — it has
   no ascenders and the glyph sits inside a disc — so it gets a little more. */
.brand__mark--badge{height:30px}
.brand__lockup{height:34px;width:auto;display:block;margin:0 0 18px}
@media (max-width:520px){ .brand__mark{height:22px} .brand__mark--badge{height:25px} }

/* Numeric columns: the header must sit over its own numbers.
   `table.grid th` sets text-align:left and out-specifies `.num` (0,0,1,2 beats
   0,0,1,0), so headers went left while values went right and the two drifted to
   opposite ends of a wide column. Right-align the header, and let the column
   shrink to its contents so the number is next to its label rather than a hand
   span away from it. */
table.grid th.num{text-align:right}
table.grid th.num,table.grid td.num{width:1%;white-space:nowrap}

/* The queue is a working screen, not a reading screen. It gets the full window
   and larger type: this is where the posting team spends the day, and squinting
   at 12.5px inside a 1400px column on a 2560px monitor helps nobody. */
.wrap.wide{max-width:none;padding-left:26px;padding-right:26px}
.wrap.wide table.grid{font-size:13.5px}
.wrap.wide table.grid td{padding:10px 12px}
.wrap.wide table.grid th{font-size:11px}

/* Filters on one row. They wrap only when the window genuinely cannot hold
   them, rather than at a fixed min-width that assumed a narrow column. */
.filters.wide{flex-wrap:nowrap;align-items:flex-end;overflow-x:auto}
.filters.wide .f{min-width:0;flex:1 1 0}
.filters.wide .f.grow{flex:2 1 0;min-width:170px}
.filters.wide select,.filters.wide input{font-size:13px;padding:8px 9px;width:100%}
.filters.wide label{white-space:nowrap}
@media (max-width:1250px){ .filters.wide{flex-wrap:wrap} .filters.wide .f{flex:1 1 150px} }

/* A field that does not apply to this row. Still editable — an edge case may
   need it — but it should not read as an unanswered question. A reconciled
   deposit showing "Variance status: Open" is the application asking about a
   variance that does not exist. */
.f.muted-field label{color:var(--mid);font-weight:500}
.f.muted-field select,.f.muted-field input{background:#f6f8f9;color:var(--mid)}

/* Actions in a table cell. Each one is its own <form> — a POST, not a link, so
   it cannot be triggered by a crawler or a prefetch — and forms are block
   elements, so without this they stack into a tower. */
.row-actions{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.row-actions form{margin:0}
.row-actions .btn{padding:5px 10px;font-size:12px;white-space:nowrap}

/* A row that navigates. Paired with tr.clickable[data-href] in filter.js — the
   cursor is the only thing telling anyone it is clickable. */
table.grid tr.clickable{cursor:pointer}
table.grid tr.clickable:hover td{background:#eef6f9}

/* History. Was a run-on paragraph of Python reprs; now one row per event and
   one line per change, so two edits to the same field are visibly different
   things rather than a wall of text. */
table.grid.hist-table td{vertical-align:top;padding:9px 10px;font-size:12.5px}
table.grid.hist-table .hist-when{white-space:nowrap;color:var(--mid);
  font-variant-numeric:tabular-nums;width:1%}
.hist-who{margin-bottom:3px}
.hist-changes{margin:0;padding-left:16px}
.hist-changes li{margin:1px 0;color:var(--mid)}

/* Files chosen but not yet uploaded. The browser shows only "3 files selected"
   and no way to drop one, which is useless when the second pick replaced the
   first — see attach.js for why that mattered. */
.picked-list{margin-top:10px;border:1px solid var(--line);border-radius:4px;background:#fff}
.picked{display:flex;align-items:center;gap:10px;padding:7px 10px;
  border-bottom:1px solid #eef2f4;font-size:12.5px}
.picked:last-of-type{border-bottom:none}
.picked-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}
.picked-size{color:var(--mid);white-space:nowrap;font-variant-numeric:tabular-nums}
.picked .btn{padding:4px 9px;font-size:11.5px}
.picked-count{padding:7px 10px;color:var(--mid);font-size:12px;background:#f7fafb}

/* Second-level navigation, for the admin screens. Visibly subordinate to the
   main tabs — it is a different job from working the queue, and it should not
   compete with it. */
.subtabs{display:flex;gap:4px;flex-wrap:wrap;margin:0 0 18px;padding-bottom:10px;
  border-bottom:1px solid var(--line)}
.subtabs a{padding:6px 12px;border-radius:4px;text-decoration:none;font-size:13px;
  font-weight:600;color:var(--mid)}
.subtabs a:hover{background:#eef3f6;color:var(--ink)}
.subtabs a.on{background:var(--anchor);color:#fff}

/* One question per line, opened to answer it.
   A card each reads well for one and becomes a wall at twenty — and a wall gets
   scrolled past rather than answered. <details> rather than JavaScript: it
   works with the keyboard, it works with a screen reader, and it works with
   scripts blocked. */
.ask{border:1px solid var(--line);border-radius:5px;background:#fff;margin-bottom:8px}
.ask summary{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;
  padding:11px 14px;cursor:pointer;list-style:none;font-size:13.5px}
.ask summary::-webkit-details-marker{display:none}
.ask summary::before{content:"▸";color:var(--mid);font-size:11px;margin-right:2px}
.ask[open] summary::before{content:"▾"}
.ask[open] summary{border-bottom:1px solid var(--line);background:#fbfdfe}
.ask summary:hover{background:#f7fafb}
.ask-payer{font-weight:700}
.ask-amount{font-weight:700;font-variant-numeric:tabular-nums}
.ask-meta{color:var(--mid);font-size:12.5px}
.ask-body{padding:14px}
@media(max-width:640px){ .ask summary{gap:4px} .ask-meta{flex-basis:100%} }

/* The unkeyed-bank-file count in the internal nav. Deliberately the only badge
   in there: a tab that always has a number stops being read as a number. */
.navcount{display:inline-block;background:#ED7D31;color:#fff;border-radius:20px;
  padding:0 7px;font-size:11px;font-weight:700;line-height:17px;margin-left:5px;vertical-align:1px}

/* A spreadsheet rendered beside the entry form on the bank-file keyer. Dense on
   purpose — the job is to read a figure off it and type it, not to admire it —
   and it scrolls inside its own box so a wide export never pushes the page. */
.sheetwrap{max-height:620px;overflow:auto;border:1px solid #dce6ec;border-radius:6px;background:#fff}
.sheet{border-collapse:collapse;font:12px/1.35 ui-monospace,Consolas,monospace;white-space:nowrap}
.sheet td{border-bottom:1px solid #eef4f7;border-right:1px solid #eef4f7;padding:4px 8px;
  max-width:280px;overflow:hidden;text-overflow:ellipsis}
.sheet tr:first-child td{position:sticky;top:0;background:#eef3f6;font-weight:700;z-index:1}
.sheet tr:hover td{background:#fffbf2}

/* --- editing a queue row in place ------------------------------------------- */
/* The row is a button as far as the pointer is concerned, but only where that
   is true: the View link inside it still behaves like a link. */
table.grid tr.qrow{cursor:pointer}
table.grid tr.qrow:focus{outline:2px solid var(--blue);outline-offset:-2px}
table.grid tr.qrow.open td{background:#eef6fb;border-bottom-color:#cfe2ef}
table.grid tr.qedit>td{background:#f7fbfd;padding:14px 12px 16px;border-bottom:2px solid var(--line)}
.rowform{margin:0}
/* auto-fit rather than a fixed column count: this sits inside a wide table and
   has to survive a narrow window without the fields collapsing to nothing. */
.rowgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px}
.rowgrid>*{min-width:0}
.rowactions{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:12px}
.rowactions .muted{font-size:11.5px;color:var(--mid);flex:1;min-width:220px}
.rowform.excl{display:flex;gap:8px;align-items:center;flex-wrap:wrap;
  margin-top:12px;padding-top:12px;border-top:1px dashed var(--line)}
.rowform.excl label{font-size:11.5px;font-weight:700;color:var(--mid);
  text-transform:uppercase;letter-spacing:.4px}
.rowform.excl .muted{font-size:11.5px;color:var(--mid);flex:1;min-width:200px}
.rowform.excl select,.rowform.excl input[type=text]{width:auto;min-width:170px}

/* Count badge on an admin tab. Same idea as .navcount but sized for the
   smaller sub-tab row, and never the reason a tab wraps to a second line. */
.subtabs .tabn{display:inline-block;background:rgba(0,0,0,.09);border-radius:9px;
  padding:0 6px;margin-left:4px;font-size:11px;font-weight:700;white-space:nowrap}
.subtabs a.on .tabn{background:rgba(255,255,255,.26)}

/* One reason on the not-ours-to-post list: a row that is its own little form. */
.reasonrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:8px 10px;margin:0}
.reasonrow .ord{width:64px}
.reasonrow .lbl{flex:1;min-width:200px}
.reasonrow .count{font-size:11.5px;color:var(--mid);white-space:nowrap}
.reasonrow .check{white-space:nowrap;font-size:12.5px}

/* A panel that is read far more often than it is changed: values by default,
   the form one click away. <details> so it works with JavaScript off. */
.editpanel{margin-top:14px;border-top:1px solid var(--line);padding-top:12px}
.editpanel>summary{display:inline-block;cursor:pointer;list-style:none;
  background:#fff;color:var(--anchor);border:1px solid var(--anchor);border-radius:4px;
  padding:8px 16px;font-weight:600;font-size:13.5px}
.editpanel>summary::-webkit-details-marker{display:none}
.editpanel>summary:hover{background:#eef3f6}
.editpanel[open]>summary{margin-bottom:14px;background:#eef3f6}

/* A computed money figure sitting where an input would be. Was three inline
   styles repeated per box; now one class, so the live-preview script has
   something to toggle. */
.figure{border:1px solid #bfe0cd;border-radius:4px;padding:9px 11px;
  background:#f4faf7;font-weight:700}
.figure.neg{border-color:#e8b4ae;background:#fdf6f5}
/* Provisional: typed but not saved. Deliberately quiet — a dashed underline and
   a note, not a colour change, because the colour already means neg/zero. */
.figure.provisional{border-style:dashed;position:relative}
.figure.provisional::after{content:"not saved yet";display:block;font-size:10.5px;
  font-weight:600;color:var(--mid);letter-spacing:.3px;margin-top:2px}

/* The collapsed "what you sent recently" block on the report page. Both ways of
   sending us money have to be visible without scrolling, so this one folds. */
details.recent { margin: 18px 0 0; }
details.recent > summary {
  cursor: pointer; list-style: none; padding: 8px 0;
  border-top: 1px solid var(--line);
}
details.recent > summary::-webkit-details-marker { display: none; }
details.recent > summary::before {
  content: "B8"; display: inline-block; width: 14px;
  color: var(--mid); font-size: 11px;
}
details.recent[open] > summary::before { content: "BE"; }
details.recent > summary h2 { font-size: 15px; margin: 0; }
