/* FundLedger - simple surfaces, futuristic edges. One stylesheet, no framework. */
:root {
  --bg: #070a0f;
  --bg-2: #0c111a;
  --panel: #0e141e;
  --panel-2: #121a26;
  --line: #1c2634;
  --line-2: #26344a;
  --text: #dde5f0;
  --muted: #7b8a9e;
  --accent: #35e0d0;
  --accent-dim: #1d7f78;
  --violet: #8b7bff;
  --good: #3ddc97;
  --warn: #ffc46b;
  --bad: #ff6b81;
  --radius: 10px;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono", Consolas, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background:
    radial-gradient(900px 500px at 15% -10%, #10202e 0%, transparent 60%),
    radial-gradient(700px 400px at 95% 0%, #191430 0%, transparent 55%),
    var(--bg);
  background-attachment: fixed;
  color: var(--text);
  font: 14px/1.5 "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { font-weight: 600; letter-spacing: -0.01em; margin: 0 0 14px; }
h1 { font-size: 21px; }
h2 { font-size: 16px; }
h3 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted); }

/* ---------------------------------------------------------------- shell */
.topbar {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; gap: 22px;
  padding: 0 22px; height: 56px;
  background: rgba(8, 12, 18, 0.82);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.brand {
  display: flex; align-items: center; gap: 9px;
  font-weight: 600; font-size: 15px; color: var(--text); letter-spacing: -0.02em;
}
.brand:hover { text-decoration: none; }
/* The mark, where the glowing dot used to be. Its ground is cut away, so no
   corner rounding and no box glow -- either would draw a faint square around a
   shape that has none. The artwork carries its own glow. */
.brand .brandmark { width: 28px; height: 28px; display: block; }
.brand .dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 10px var(--accent);
}
nav { display: flex; gap: 3px; flex: 1; flex-wrap: wrap; }
nav a {
  padding: 7px 12px; border-radius: 8px; color: var(--muted);
  font-size: 13px; font-weight: 500; border: 1px solid transparent;
}
nav a:hover { color: var(--text); background: var(--panel); text-decoration: none; }
nav a.on {
  color: var(--accent); background: rgba(53, 224, 208, 0.07);
  border-color: rgba(53, 224, 208, 0.22);
}
.whoami { color: var(--muted); font-size: 12px; display: flex; align-items: center; gap: 10px; }
.wrap { max-width: 1220px; margin: 0 auto; padding: 26px 22px 70px; }

/* ---------------------------------------------------------------- panels */
.panel {
  background: linear-gradient(180deg, var(--panel) 0%, var(--bg-2) 100%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  margin-bottom: 18px;
}
.panel > h2:first-child, .panel > h3:first-child { margin-top: 0; }
.grid { display: grid; gap: 18px; }
.g2 { grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
.g3 { grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); }
.g4 { grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); }
.g5 { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.spread { display: flex; justify-content: space-between; align-items: center; gap: 12px; }

/* stat tiles */
.stat {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px 16px; position: relative; overflow: hidden;
}
.stat::before {
  content: ""; position: absolute; inset: 0 auto auto 0; width: 100%; height: 1px;
  background: linear-gradient(90deg, var(--accent), transparent 70%); opacity: 0.5;
}
.stat .k { font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted); }
.stat .v { font-family: var(--mono); font-size: 19px; margin-top: 6px; letter-spacing: -0.02em; }
.stat .sub { font-size: 11px; color: var(--muted); margin-top: 3px; font-family: var(--mono); }

/* ---------------------------------------------------------------- tables */
table { width: 100%; border-collapse: collapse; font-size: 13px; }
.scroll { overflow-x: auto; }
th {
  text-align: left; padding: 9px 11px; font-size: 10.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.085em; color: var(--muted);
  border-bottom: 1px solid var(--line-2); white-space: nowrap;
}
td { padding: 10px 11px; border-bottom: 1px solid var(--line); vertical-align: top; }
tbody tr:hover td { background: rgba(53, 224, 208, 0.035); }
tbody tr:last-child td { border-bottom: none; }
.num { font-family: var(--mono); text-align: right; white-space: nowrap; }
/* A row carries a line per asset. One cell holding a single thing -- a bar, a
   figure -- reads better level with the middle of them than pinned to the top
   of the first. */
td.progcell { vertical-align: middle; }
.dim { color: var(--muted); }
.empty { padding: 26px; text-align: center; color: var(--muted); font-size: 13px; }

/* ---------------------------------------------------------------- pills */
.pill {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em;
  border: 1px solid var(--line-2); color: var(--muted); white-space: nowrap;
}
.pill.ok      { color: var(--good);   border-color: rgba(61, 220, 151, 0.35); background: rgba(61, 220, 151, 0.09); }
.pill.pending { color: var(--warn);   border-color: rgba(255, 196, 107, 0.35); background: rgba(255, 196, 107, 0.09); }
.pill.bad     { color: var(--bad);    border-color: rgba(255, 107, 129, 0.35); background: rgba(255, 107, 129, 0.09); }
.pill.info    { color: var(--violet); border-color: rgba(139, 123, 255, 0.35); background: rgba(139, 123, 255, 0.09); }
/* a conversion: green, and its own shade -- it is not an IN and not a transfer */
.pill.convert { color: var(--good);   border-color: rgba(61, 220, 151, 0.4); background: rgba(61, 220, 151, 0.10); }
.pill.in      { color: var(--good);   border-color: rgba(61, 220, 151, 0.3); }
.pill.out     { color: var(--bad);    border-color: rgba(255, 107, 129, 0.3); }
.pos { color: var(--good); }
.neg { color: var(--bad); }

/* progress */
.bar { height: 5px; background: var(--line); border-radius: 3px; overflow: hidden; min-width: 70px; }
.bar > i {
  display: block; height: 100%;
  background: linear-gradient(90deg, var(--accent-dim), var(--accent));
  box-shadow: 0 0 8px rgba(53, 224, 208, 0.5);
}

/* ---------------------------------------------------------------- forms */
label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em;
        color: var(--muted); margin-bottom: 5px; }
input, select, textarea {
  width: 100%; padding: 9px 11px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line-2); border-radius: 8px;
  font: inherit; outline: none; transition: border-color .12s, box-shadow .12s;
}
input[type=number], input[inputmode=decimal], .mono { font-family: var(--mono); }
input:focus, select:focus, textarea:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(53, 224, 208, 0.13);
}
input::placeholder { color: #4d5b6d; }
textarea { resize: vertical; min-height: 62px; }
.field { flex: 1 1 175px; min-width: 145px; margin-bottom: 12px; }
.field.wide { flex: 1 1 100%; }
.field .err { color: var(--bad); font-size: 11.5px; margin-top: 4px; text-transform: none;
              letter-spacing: 0; }
.field.bad input, .field.bad select { border-color: var(--bad); }
.hint { font-size: 11.5px; color: var(--muted); margin-top: 4px; }

button, .btn {
  display: inline-block; padding: 9px 15px; border-radius: 8px; cursor: pointer;
  font: 500 13px/1.2 inherit; border: 1px solid var(--line-2);
  background: var(--panel-2); color: var(--text); transition: all .12s;
}
button:hover, .btn:hover { border-color: var(--accent-dim); text-decoration: none; }
.btn-primary {
  background: linear-gradient(180deg, rgba(53,224,208,.16), rgba(53,224,208,.06));
  border-color: rgba(53, 224, 208, 0.45); color: var(--accent); font-weight: 600;
}
.btn-primary:hover { box-shadow: 0 0 16px rgba(53, 224, 208, 0.22); }
.btn-deal {
  background: linear-gradient(180deg, rgba(139,123,255,.18), rgba(139,123,255,.06));
  border-color: rgba(139, 123, 255, 0.45); color: var(--violet); font-weight: 600;
}
.btn-deal:hover { box-shadow: 0 0 16px rgba(139, 123, 255, 0.25); }
.btn-sm { padding: 5px 10px; font-size: 12px; }
.btn-danger { color: var(--bad); border-color: rgba(255, 107, 129, 0.35); }
form.inline { display: inline; }

/* ---------------------------------------------------------------- flash */
.flash {
  padding: 11px 15px; border-radius: 9px; margin-bottom: 16px; font-size: 13px;
  border: 1px solid var(--line-2); background: var(--panel);
}
.flash.ok  { border-color: rgba(61, 220, 151, 0.4); color: var(--good);
             background: rgba(61, 220, 151, 0.07); }
.flash.bad { border-color: rgba(255, 107, 129, 0.4); color: var(--bad);
             background: rgba(255, 107, 129, 0.07); }

/* ---------------------------------------------------------------- login */
.login-wrap { min-height: 100vh; display: grid; place-items: center; padding: 20px; }
.login-card { width: 100%; max-width: 358px; }
.login-card .panel { padding: 30px; }
.login-mark {
  text-align: center; margin-bottom: 22px; font-size: 20px; font-weight: 600;
  letter-spacing: -0.02em;
}
.login-mark span { color: var(--accent); text-shadow: 0 0 18px rgba(53, 224, 208, 0.55); }
/* the full lockup carries the name itself, so nothing is written beside it */
.login-logo { display: block; width: 100%; max-width: 300px; margin: 0 auto 2px; }
.login-mark .tag {
  display: block; font-size: 11px; color: var(--muted); font-weight: 400;
  text-transform: uppercase; letter-spacing: 0.16em; margin-top: 7px;
}

/* ---------------------------------------------------------------- misc */
.chain { list-style: none; margin: 0; padding: 0; }
.chain li {
  position: relative; padding: 12px 0 12px 26px; border-bottom: 1px solid var(--line);
}
.chain li:last-child { border-bottom: none; }
.chain li::before {
  content: ""; position: absolute; left: 4px; top: 18px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 8px var(--accent);
}
.chain li.pending::before { background: var(--warn); box-shadow: 0 0 8px var(--warn); }
.chain li::after {
  content: ""; position: absolute; left: 7.5px; top: 28px; bottom: -4px; width: 1px;
  background: var(--line-2);
}
.chain li:last-child::after { display: none; }
.kv { display: grid; grid-template-columns: 155px 1fr; gap: 9px 16px; font-size: 13px; }
.kv dt { color: var(--muted); font-size: 12px; }
.kv dd { margin: 0; font-family: var(--mono); }
.tabs { display: flex; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
.tabs a { padding: 7px 14px; border-radius: 8px; border: 1px solid var(--line);
          color: var(--muted); font-size: 13px; }
.tabs a.on { color: var(--accent); border-color: rgba(53, 224, 208, 0.4);
             background: rgba(53, 224, 208, 0.07); }
.hidden, [hidden] { display: none !important; }
/* small tag inside an uppercase h3 - must opt out of the heading's transform */
.only {
  display: inline-block; margin-left: 7px; padding: 2px 7px; border-radius: 999px;
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: none; color: var(--violet);
  border: 1px solid rgba(139, 123, 255, 0.32); background: rgba(139, 123, 255, 0.08);
  vertical-align: middle;
}
code { font-family: var(--mono); font-size: 12px; color: var(--violet); }

@media (max-width: 720px) {
  .topbar { height: auto; padding: 10px 14px; flex-wrap: wrap; }
  .wrap { padding: 18px 14px 60px; }
  .kv { grid-template-columns: 1fr; gap: 3px 0; }
  .kv dd { margin-bottom: 9px; }
}

/* ---------------------------------------------------------------- review modal */
.modal-back {
  position: fixed; inset: 0; z-index: 90;
  display: grid; place-items: center; padding: 20px;
  background: rgba(4, 7, 11, 0.72);
  backdrop-filter: blur(3px);
}
.modal {
  width: 100%; max-width: 310px; max-height: 78vh; overflow-y: auto;
  background: linear-gradient(180deg, var(--panel) 0%, var(--bg-2) 100%);
  border: 1px solid var(--line-2); border-radius: 12px; padding: 15px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.7);
}
.modal h2 { font-size: 13.5px; margin: 0 0 11px; }
.modal-list { grid-template-columns: 42% 1fr; gap: 5px 10px; font-size: 12px; }
.modal-list dt {
  color: var(--muted); font-size: 11px;
  border-bottom: 1px solid var(--line); padding-bottom: 5px;
}
.modal-list dd {
  margin: 0; font-family: var(--mono); font-size: 12px; word-break: break-word;
  border-bottom: 1px solid var(--line); padding-bottom: 5px;
}
.modal .row { gap: 7px; margin-top: 13px !important; }
.modal button { padding: 6px 11px; font-size: 12px; }
input:disabled, select:disabled {
  opacity: .62; cursor: not-allowed; background: var(--bg-2);
}

/* ------------------------------------------------- one-tap action rows
   Approve / Confirm live here. A table would push the button off the right of a
   phone screen and force a sideways scroll before it could be tapped, so these
   rows wrap instead: the button is always reachable at any width. */
.actionrow {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
  padding: 11px 0; border-bottom: 1px solid var(--line);
}
.actionrow:last-child { border-bottom: none; padding-bottom: 0; }
.actioninfo { flex: 1 1 210px; min-width: 0; }
.actioninfo > div { line-height: 1.45; }
.actionbtns { display: flex; gap: 7px; flex: 0 0 auto; }
.actionbtns button, .actionbtns .btn { padding: 8px 16px; }
@media (max-width: 560px) {
  .actionbtns { width: 100%; }
  .actionbtns form { flex: 1 1 auto; }
  .actionbtns button { width: 100%; }        /* full-width tap target on a phone */
}

/* ------------------------------------------------- holder rows (Accounts)
   Reads as one table: a header strip, then a row per holder with a divider
   between. Each row is a <details> so it opens to show that holder's accounts --
   native element, no JavaScript. Header and rows share one grid template, which
   is what keeps the columns lined up down the page. */
.holderhead, .holder > summary {
  display: grid;
  grid-template-columns: minmax(150px, 2.2fr) 92px 90px minmax(120px, 1fr) minmax(120px, 1fr);
  align-items: center;
  gap: 12px;
}
.holderhead {
  padding: 2px 11px 10px;
  font-size: 10.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.085em; color: var(--muted);
  border-bottom: 1px solid var(--line-2);
}
.holder { border-bottom: 1px solid var(--line); }
.holder:last-child { border-bottom: none; }
.holder > summary {
  cursor: pointer; list-style: none; user-select: none;
  padding: 12px 11px; border-radius: 8px; transition: background .12s;
}
.holder > summary::-webkit-details-marker { display: none; }
.holder > summary:hover { background: rgba(53, 224, 208, 0.035); }
.holder > summary:hover .hname { color: var(--accent); }
.holder[open] > summary { background: rgba(53, 224, 208, 0.05); }
.hname { position: relative; padding-left: 16px; font-weight: 600; font-size: 14px; }
.hname::before {
  content: "▸"; position: absolute; left: 0; color: var(--muted);
  font-size: 10px; transition: transform .12s; display: inline-block;
}
.holder[open] .hname::before { transform: rotate(90deg); color: var(--accent); }
.holder > summary .num { font-size: 13.5px; }
.hcount { font-size: 12.5px; }
.holderbody {
  margin: 0 11px 14px; padding: 4px 14px 0;
  border-left: 2px solid var(--line-2);
}
@media (max-width: 720px) {
  .holderhead { display: none; }
  .holder > summary { grid-template-columns: 1fr auto; row-gap: 4px; }
  .holder > summary .num { text-align: right; }
  .hcount { grid-column: 1; }
  .holderbody { margin-left: 0; padding-left: 8px; }
}

/* ------------------------------------------------- assets reported apart
   INR and USDT are different things and are never added together, so the
   dashboard gives each its own line and its own total. */
.assetline {
  display: flex; align-items: baseline; gap: 8px;
  font-family: var(--mono); font-size: 13px; margin-top: 6px;
}
.assetline .alabel {
  font-size: 9.5px; letter-spacing: 0.08em; color: var(--muted);
  min-width: 32px; font-family: inherit;
}
.assettotal {
  font-size: 20px; margin: -4px 0 12px;
  padding-bottom: 10px; border-bottom: 1px solid var(--line-2);
  text-align: left;
}
h3 .atag { margin-left: 6px; vertical-align: middle; }
.atag {
  font-size: 10px; font-weight: 700; letter-spacing: 0.1em; color: var(--accent);
  padding: 2px 8px; border-radius: 999px;
  border: 1px solid rgba(53, 224, 208, 0.3); background: rgba(53, 224, 208, 0.07);
}

/* ------------------------------------------------- dashboard side column
   The check queue is the one part of the dashboard you act on, so it sits in
   its own column and stays put while the ledger scrolls beside it. */
.dashgrid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 18px;
  align-items: start;
}
/* a grid column will not shrink below its content unless told to, and the
   tables inside are wide -- without this the page scrolls sideways on a phone */
.dashmain, .dashside { min-width: 0; }
.dashside > .panel {
  position: sticky; top: 74px;
  max-height: calc(100vh - 100px); overflow-y: auto;
}
/* the column is narrow, so its rows stack instead of squeezing. the info block
   must stop growing once stacked, or flex stretches it down the whole row */
.dashside .actionrow { flex-direction: column; align-items: stretch; gap: 8px; }
.dashside .actioninfo { flex: 0 0 auto; }
.dashside .actionbtns { width: 100%; }
.dashside .actionbtns form { flex: 1 1 auto; }
.dashside .actionbtns button { width: 100%; }
@media (max-width: 1080px) {
  .dashgrid { grid-template-columns: minmax(0, 1fr); }
  .dashside > .panel { position: static; max-height: none; }
}

/* an amount larger than the account holds, flagged while it is typed */
input.overdrawn { border-color: var(--bad); box-shadow: 0 0 0 3px rgba(255,107,129,.12); }

/* Confirmation that floats over the page. A banner inserted into the flow would
   push whatever you are reading down the screen every time you press a button. */
.toast {
  position: fixed; left: 50%; bottom: 22px; transform: translate(-50%, 8px);
  padding: 10px 18px; border-radius: 999px; font-size: 13px; z-index: 60;
  border: 1px solid rgba(61, 220, 151, 0.4); color: var(--good);
  background: var(--panel); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  opacity: 0; pointer-events: none; transition: opacity .15s, transform .15s;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }
.toast.bad  { border-color: rgba(255, 107, 129, 0.4); color: var(--bad); }

/* A statement reads in two columns: what left on the left, what arrived on the
   right. Each figure carries its own asset, because a conversion moves two. */
.money { white-space: nowrap; vertical-align: top; }
.money .acct { font-size: 11px; color: var(--dim); font-weight: 400; }
.money .waiting { opacity: .55; }
.money .waiting .acct::after { content: " · awaited"; }
.money.debit  { border-right: 1px solid var(--line); }
/* Update a wallet in place -- typing the real figure where the old one is shown
   is less work than opening a form to say the same thing. */
.inline-update { display: flex; gap: 6px; justify-content: flex-end; }
.inline-update input { width: 108px; padding: 5px 8px; font-size: 12.5px; text-align: right; }
.inline-update .btn { padding: 5px 11px; font-size: 12.5px; }

/* The check queue holds three different asks, and they used to look identical:
   something a client already moved, something not yet counted, and a debt still
   to be released. A colour down the edge tells them apart before you read. */
.actionrow.kind-posted      { border-left: 3px solid var(--violet); padding-left: 11px; }
.actionrow.kind-unconfirmed { border-left: 3px solid var(--warn);   padding-left: 11px; }
.actionrow.kind-due         { border-left: 3px solid var(--good);   padding-left: 11px; }

.kindtag { font-size: 10.5px; letter-spacing: .04em; text-transform: uppercase;
           padding: 2px 7px; border-radius: 5px; white-space: nowrap; }
.kindtag.posted      { color: var(--violet); background: rgba(139, 123, 255, 0.12); }
.kindtag.unconfirmed { color: var(--warn);   background: rgba(255, 196, 107, 0.12); }
.kindtag.due         { color: var(--good);   background: rgba(61, 220, 151, 0.12); }
/* A standing ask -- nothing has moved, so it gets its own colour rather than
   sitting among the things that need confirming. */
.actionrow.kind-ask { border-left: 3px solid var(--accent); padding-left: 11px; }

/* Column headings double as the sort control -- the thing you want to sort by is
   already the thing you are looking at. */
.sorth { color: inherit; text-decoration: none; display: inline-flex; gap: 4px; }
.sorth:hover { color: var(--text); }
.sorth.on { color: var(--accent); }
.sorth .arrow { font-size: 10px; opacity: .8; }

/* Queue rows: what left and what arrived, side by side and coloured, so a
   conversion is not approved on the strength of one of its two figures. */
.qlegs { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 5px 0 2px; }
.qleg { display: inline-flex; gap: 6px; align-items: baseline; font-family: var(--mono, monospace);
        font-size: 12.5px; border-left: 2px solid transparent; padding-left: 7px; }
.qleg.credit { border-left-color: rgba(61, 220, 151, 0.5); }
.qleg.debit  { border-left-color: rgba(255, 107, 129, 0.5); }
.qleg .acct { font-size: 11px; color: var(--muted); font-family: inherit; }

/* What was done, as the row's heading. The direction pill describes the shape of
   a movement; this says what job it was. */
.qhead { font-weight: 600; font-size: 13.5px; letter-spacing: .01em;
         display: flex; flex-wrap: wrap; gap: 7px; align-items: center; margin-bottom: 3px; }

/* A tick-box that reveals a row of fields, rather than a row that is always
   there asking about something most movements do not have. */
.checkline { display: inline-flex; align-items: center; gap: 8px; margin: 4px 0 10px;
             font-size: 13px; color: var(--muted); cursor: pointer; }
.checkline input { width: 15px; height: 15px; accent-color: var(--accent); }

/* What was done, in the colours of the thing itself. This is what you scan for,
   so it leads; whether it was confirmed or checked is bookkeeping about it and
   sits underneath in small grey type. */
.act { display: inline-block; padding: 3px 9px; border-radius: 6px; font-size: 11.5px;
       font-weight: 700; letter-spacing: .06em; border: 1px solid transparent; }
.act-transfer      { color: var(--violet); background: rgba(139,123,255,.13); border-color: rgba(139,123,255,.35); }
.act-convert       { color: var(--accent); background: rgba(53,224,208,.13);  border-color: rgba(53,224,208,.35); }
.act-new-deal      { color: var(--good);   background: rgba(61,220,151,.13);  border-color: rgba(61,220,151,.35); }
.act-released      { color: var(--good);   background: rgba(61,220,151,.10);  border-color: rgba(61,220,151,.3); }
.act-request       { color: var(--warn);   background: rgba(255,196,107,.13); border-color: rgba(255,196,107,.35); }
.act-wallet-update { color: #7fb2ff;       background: rgba(127,178,255,.13); border-color: rgba(127,178,255,.35); }
.act-entry         { color: var(--muted);  background: rgba(123,138,158,.12); border-color: rgba(123,138,158,.3); }

/* the status that used to shout */
.subtle { font-size: 10.5px; color: var(--muted); margin-top: 4px; letter-spacing: .03em; }
.qhead .pill, .qhead .kindtag { font-weight: 400; opacity: .85; }
/* the two sides of a request are the choice being made, so they read as a choice */
#sidetabs a { font-weight: 700; letter-spacing: .06em; }
/* the tabs are choices, not links -- no underline on hover */
.tabs a, .tabs a:hover, .tabs a:focus { text-decoration: none; }

/* A searchable dropdown: an input that filters the real <select> behind it.
   The select still submits and is still what other scripts read. */
.ss { position: relative; }
.ss-hidden { position: absolute; opacity: 0; pointer-events: none; height: 0; width: 0; }
.ss-input { width: 100%; }
.ss-list { position: absolute; z-index: 40; left: 0; right: 0; top: 100%; margin-top: 4px;
           max-height: 260px; overflow-y: auto; background: var(--panel-2);
           border: 1px solid var(--line-2); border-radius: 9px;
           box-shadow: 0 10px 28px rgba(0,0,0,.45); }
.ss-opt { padding: 8px 11px; font-size: 13px; cursor: pointer; }
.ss-opt:hover, .ss-opt.on { background: rgba(53,224,208,.12); color: var(--text); }
.ss-none { padding: 8px 11px; font-size: 12.5px; color: var(--muted); }

/* Charges: money the deal cost somebody. Red down the edge so it reads apart
   from the figures that describe what it made. */
.stat.charges { border-left: 3px solid rgba(255, 107, 129, 0.55); }
.stat.charges .v { color: var(--bad); }
.act-charge { color: var(--bad); background: rgba(255,107,129,.13);
              border-color: rgba(255,107,129,.35); }
/* and the same in the chain, so a charge leg is not mistaken for a movement */
/* A charge hangs off the leg above it: the red bar says so. It keeps the same
   text indent as every other row -- shifting it left dragged the words over the
   dot and left the column ragged -- and gives up the dot, since the bar is
   already its marker. */
.chain li.charge {
  border-left: 3px solid rgba(255, 107, 129, 0.45);
  padding-left: 23px;                     /* 3px border + 23 = the 26px others use */
}
.chain li.charge::before { display: none; }
.chain li.charge::after { left: 4.5px; }
/* a pager arm with nowhere to go */
.btn.off { opacity: .35; pointer-events: none; }

/* ---------------------------------------------------------------- proof */
.proofs { display: flex; flex-wrap: wrap; gap: 10px; }
.proof {
  position: relative; width: 132px; height: 132px; border-radius: 9px;
  overflow: hidden; border: 1px solid var(--line); background: var(--panel-2);
}
.proof img { width: 100%; height: 100%; object-fit: cover; cursor: zoom-in; display: block; }
.proof .doc {
  display: flex; align-items: center; justify-content: center; height: 100%;
  padding: 10px; font-size: 11px; text-align: center; word-break: break-all;
}
.proof .dl {
  position: absolute; right: 6px; bottom: 6px; width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center; border-radius: 7px;
  font-size: 14px; line-height: 1; text-decoration: none; color: var(--text);
  background: rgba(10, 14, 20, 0.78); border: 1px solid var(--line-2);
}
.proof .dl:hover { color: var(--accent); border-color: var(--accent-dim); }

#lightbox {
  position: fixed; inset: 0; z-index: 60; display: flex; cursor: zoom-out;
  align-items: center; justify-content: center; padding: 28px;
  background: rgba(4, 7, 11, 0.88);
}
#lightbox[hidden] { display: none; }
#lightbox img {
  max-width: 100%; max-height: 100%; border-radius: 10px;
  border: 1px solid var(--line-2);
}
.proof .rm {
  position: absolute; right: 5px; top: 5px; width: 24px; height: 24px; padding: 0;
  display: flex; align-items: center; justify-content: center; border-radius: 7px;
  font-size: 15px; line-height: 1; color: var(--bad);
  background: rgba(10, 14, 20, 0.82); border: 1px solid rgba(255, 107, 129, 0.35);
}
.proof .rm:hover { background: rgba(255, 107, 129, 0.18); }

/* proof picked inside a one-line action row */
.inline-update { flex-wrap: wrap; align-items: center; }
.inline-update .proofpick { width: auto; text-align: left; font-size: 11.5px; max-width: 190px; }
.inline-update .proofs { flex-basis: 100%; justify-content: flex-end; margin-top: 6px; }
.inline-update .proof { width: 78px; height: 78px; }
.inline-update .proof .rm { width: 20px; height: 20px; font-size: 13px; }
.nowrap { white-space: nowrap; }
.nowrap form + form { margin-left: 5px; }

/* A box whose value is decided for you: shown, but plainly not yours to type in */
input.locked, select.locked {
  color: var(--muted); background: var(--panel); border-style: dashed;
  pointer-events: none; user-select: none;
}

/* an amount box with a Max beside it */
/* "Max" sits inside the amount box, at its right edge -- beside it, it read as
   a second field and left a gap in the row. */
.withmax { position: relative; display: block; }
.withmax input { width: 100%; padding-right: 66px; }
.withmax .btn {
  position: absolute; right: 5px; top: 50%; transform: translateY(-50%);
  padding: 4px 10px; font-size: 11.5px; line-height: 1.3;
}
.hint.overpct { color: var(--bad); }
/* a row whose fields carry hints: line the boxes up, not their bottoms */
.row.top { align-items: flex-start; }
/* a value that was decided elsewhere: shown, not asked for */
.fixedvalue {
  padding: 9px 12px; border: 1px dashed var(--line-2); border-radius: 8px;
  background: var(--panel); font: 500 13px/1.3 var(--mono); color: var(--text);
}

/* something is waiting on that tab */
.dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--bad); margin-left: 5px; vertical-align: top;
  box-shadow: 0 0 6px rgba(255, 107, 129, 0.7);
}

/* the queue's controls read as one row: same height, same rhythm */
.actionbtns { align-items: stretch; }
.actionbtns form { display: flex; gap: 6px; }
.actionbtns input, .actionbtns button, .actionbtns .btn {
  height: 36px; padding: 0 16px; display: inline-flex; align-items: center;
  justify-content: center; font-size: 13px;
}
.actionbtns input { width: 104px; text-align: left; }

/* ------------------------------------------------------- the client app
   Read on a phone as often as at a desk, by people who see it once a week
   rather than all day. Everything runs a step larger there; the office app,
   which shows far more at once, keeps its density. */
body.client { font: 15px/1.55 "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
body.client h1 { font-size: 25px; }
body.client h2 { font-size: 18px; }
body.client h3 { font-size: 14px; }
body.client table { font-size: 15px; }
body.client th { font-size: 12px; }
body.client td { padding: 12px 11px; }
body.client .stat .k { font-size: 12.5px; }
body.client .stat .v { font-size: 23px; }
body.client .stat .sub { font-size: 12.5px; }
body.client .kv { font-size: 15px; }
body.client .kv dt { font-size: 13.5px; }
body.client label { font-size: 12.5px; }
body.client .hint,
body.client .empty { font-size: 13.5px; }
body.client .pill { font-size: 11px; }
body.client .btn, body.client button { font-size: 14px; }
body.client .btn-sm { font-size: 13px; }
body.client input, body.client select, body.client textarea { font-size: 15px; }
/* the small print set straight on the element in a template, lifted with it */
body.client [style*="font-size:11px"] { font-size: 12.5px !important; }
body.client [style*="font-size:11.5px"] { font-size: 13px !important; }
body.client [style*="font-size:12px"] { font-size: 13.5px !important; }

/* ------------------------------------------------- who is on a deal
   A short list of names, so it reads as a list of names: one chip each, the
   owner marked rather than shouted, and the way to remove somebody kept small
   enough that it is not the first thing the eye lands on. */
.addmember { display: flex; align-items: center; gap: 8px; }
.addmember select { width: 190px; }
.members { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.member {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 6px 8px 6px 13px; border: 1px solid var(--line-2);
  border-radius: 999px; background: var(--panel-2); font-size: 13px;
}
.member .who { font-weight: 500; letter-spacing: -0.01em; }
.member.owner { border-color: rgba(53, 224, 208, 0.32); padding-right: 13px; }
.member .tag {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--accent-dim);
}
.member .rm {
  width: 20px; height: 20px; padding: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; line-height: 1; color: var(--muted);
  background: transparent; border: 1px solid transparent;
}
.member .rm:hover { color: var(--bad); border-color: rgba(255, 107, 129, 0.35); }
.members:empty { display: none; }

/* a stat tile that is also a filter: it reads as a figure, clicks as a tab */
.stat.count { display: block; color: inherit; text-decoration: none; }
.stat.count:hover { border-color: var(--line-2); text-decoration: none; }
.stat.count.on { border-color: rgba(53, 224, 208, 0.45); }
.stat.count .v { font-size: 22px; }

/* The one place a paste lands: a screenshot is attached because this box was
   asked for it, never because Ctrl-V happened to be pressed on the page. */
.pastezone {
  display: block; margin-top: 10px; padding: 9px 14px;
  border: 1px dashed var(--line-2); border-radius: 8px; background: transparent;
  color: var(--muted); font-size: 12.5px; text-align: left; width: 100%;
}
.pastezone:hover { border-color: var(--accent-dim); color: var(--text); }
.pastezone:focus {
  outline: none; border-style: solid; border-color: var(--accent);
  color: var(--text); box-shadow: 0 0 0 3px rgba(53, 224, 208, 0.12);
}
.pastezone:focus::after { content: " - now press Ctrl-V"; color: var(--accent); }

/* Something you are allowed to do, that you should know the cost of first. */
.warn { color: var(--warn); }

/* Names are stored in capitals, so they are typed in capitals: what you see
   while entering one is what the ledger will show. */
input.caps { text-transform: uppercase; }

/* ------------------------------------------------- the standing strip
   Five figures in the width the three used to take: one row, no wrapping onto
   a second line, nothing clipped. The tiles share the row equally and the
   number inside shrinks to fit rather than running past its own edge. */
.standing {
  display: grid; gap: 10px; margin-bottom: 18px;
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
.standing .stat {
  display: flex; flex-direction: column; justify-content: space-between;
  padding: 12px 13px 13px; min-width: 0;
}
.standing .stat .k {
  font-size: 10px; line-height: 1.3; min-height: 2.6em; letter-spacing: 0.07em;
}
.standing .stat .v {
  font-size: clamp(13px, 1.15vw, 18px); margin-top: 8px;
  white-space: nowrap; font-variant-numeric: tabular-nums; min-width: 0;
}
/* narrow screens have no row to share, so they wrap rather than squeeze */
@media (max-width: 1100px) {
  .standing { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
}

/* A question with one possible answer, shown as the answer. The dropdown is
   still there and still what submits -- it is simply not asked. */
.settled-as { display: none; }
.field.settled .settled-as { display: block; }
.field.settled > select,
.field.settled > .ss { display: none; }

/* The earlier legs of a long chain: off screen until asked for, and the press
   sits at the foot of the list where the eye ends up. */
.chain li.extra { display: none; }
.chain.all li.extra { display: list-item; }
.morelegs { margin-top: 10px; }

/* the charges of a deal on their own, without the legs they hang off */
.chain.onlycharges li:not(.charge) { display: none; }
.chain.onlycharges li.charge.extra { display: list-item; }

/* What of a deal reached them and what has gone on again -- the two figures the
   client actually works from, so they get room of their own rather than being
   squeezed into the corner by the bar beside them. */
.dealflow {
  display: grid; align-items: center; gap: 14px 34px;
  grid-template-columns: minmax(150px, auto) minmax(150px, auto) minmax(200px, 1fr);
  margin: 12px 0 16px; padding: 14px 16px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel-2);
}
.dealflow .k { font-size: 11px; text-transform: uppercase; letter-spacing: 0.09em;
               color: var(--muted); }
.dealflow .v { font-family: var(--mono); font-size: 18px; margin-top: 5px;
               letter-spacing: -0.02em; }
.dealflow .barcell .k { margin-bottom: 7px; display: inline-block; }
@media (max-width: 760px) {
  .dealflow { grid-template-columns: 1fr 1fr; }
  .dealflow .barcell { grid-column: 1 / -1; }
}

/* Reports: one panel, several views. The tab bar sits at the top of it and the
   sections below take turns, so nothing has to be scrolled past. */
.reportbook > .tabs { margin-bottom: 16px; }
.reportbook > section > .standing { margin-bottom: 10px; }
.reportbook h3 { margin-top: 4px; }

/* Opening a door, beside the red one that shuts it. */
.btn-go { color: var(--good); border-color: rgba(61, 220, 151, 0.4); }
.btn-go:hover { box-shadow: 0 0 14px rgba(61, 220, 151, 0.18); }

/* ================================================================ phones
   Measured with mobile_audit.py at 390x844, not guessed at. Four things make a
   page unusable in a hand, and each is answered below: a menu that eats the
   screen, taps too small to hit, a field that zooms the page in when it takes
   focus, and text nobody can read without pinching. */
@media (max-width: 720px) {
  /* The bar at the top: one row for who you are, one strip for where to go.
     Ten sections wrapping into five stacked rows took 400px -- half the screen
     -- before the page even started. The strip scrolls sideways instead, one
     row tall, and nav-strip.js brings the section you are on into view. */
  .topbar { height: auto; padding: 8px 0 0; gap: 0; align-items: center; }
  .brand { order: 1; padding: 0 14px 8px; }
  .whoami { order: 2; margin-left: auto; padding: 0 14px 8px; font-size: 12.5px; }
  nav {
    order: 3; flex: 1 0 100%; flex-wrap: nowrap;
    overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
    gap: 2px; padding: 6px 10px; border-top: 1px solid var(--line);
    scrollbar-width: none;
  }
  nav::-webkit-scrollbar { display: none; }
  nav a { flex: 0 0 auto; padding: 9px 13px; font-size: 13.5px; }

  /* A finger is about 44px across, and a 27px button is a miss. */
  button, .btn { padding: 10px 16px; min-height: 40px; }
  .btn-sm { padding: 7px 13px; font-size: 12.5px; min-height: 36px; }
  .whoami .btn-sm { min-height: 36px; padding: 7px 12px; }
  .tabs a { padding: 10px 15px; }
  .actionbtns button, .actionbtns .btn { min-height: 42px; }

  /* 16px is the line below which a phone zooms the page in as soon as a field
     takes focus -- and it does not zoom back out afterwards. */
  input, select, textarea { font-size: 16px; min-height: 44px; padding: 11px 12px; }
  textarea { min-height: 78px; }
  /* a 15px checkbox is a miss; 20px is still small but it can be hit */
  input[type=checkbox], input[type=radio] {
    min-height: 0; width: 20px; height: 20px; margin-right: 4px;
  }
  /* one question to a row: side by side, each half was too narrow to read */
  .field { flex: 1 1 100%; min-width: 0; }
  /* Filters are the exception, and a GET form is exactly what a filter is: six
     stacked boxes pushed the list itself off the screen, so they go two to a
     line with the search box across the top. */
  form[method="get"] .field { flex: 1 1 calc(50% - 6px); }
  form[method="get"] .field:first-child,
  form[method="get"] .field.wide { flex: 1 1 100%; }

  /* Text that was sized for a desktop table. */
  label { font-size: 12px; }
  .hint, .field .err { font-size: 12.5px; }
  th { font-size: 11.5px; }
  td { padding: 11px 10px; }
  /* the more specific desktop rules have to be answered by name, or they win */
  .pill, body.client .pill { font-size: 11.5px; padding: 3px 10px; }
  .acct, .money .acct, .qleg .acct, .stat .sub, .kv dt { font-size: 12px; }
  .kindtag, .subtle, .holderhead, .sorth .arrow { font-size: 11.5px; }
  .atag, .only, .tag, .member .tag { font-size: 11.5px; }
  .dealflow .k { font-size: 12px; }
  .stat .k { font-size: 11.5px; }
  .standing .stat .k { font-size: 11.5px; min-height: 0; }
  .standing .stat .v { font-size: 16px; }
  /* ponytail: the templates set a few sizes inline, which a stylesheet cannot
     reach without this. Delete the rule when they become classes. */
  [style*="font-size:11px"], [style*="font-size:11.5px"] { font-size: 12.5px !important; }

  /* A wide table keeps its columns and scrolls inside its own box: crushing
     eight columns into 350px put one word on each line. Only tables that really
     have that many columns are pushed out -- a short one still fits as it is. */
  .scroll { scrollbar-width: thin; }
  .scroll::-webkit-scrollbar { height: 5px; }
  .scroll::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 3px; }
  .scroll > table:has(tbody tr > *:nth-child(5)) { min-width: 560px; }
  /* a reference is one word: D-2026-0001 broken over three lines is unreadable.
     Only linked refs -- a wrapped date or note is fine where it is. */
  td a.mono { white-space: nowrap; }
  /* likewise a timestamp, an amount, or a route, once the table can scroll */
  .scroll td.mono, .scroll td .money, .scroll td.num { white-space: nowrap; }
  .scroll .flowpath { white-space: nowrap; }

  h1 { font-size: 19px; }
  .panel { padding: 14px; }
  .spread { flex-wrap: wrap; }
}
