/* Nice Panel — green "leaf" theme, dark + light, mobile-first with a real
   desktop layout. No external assets: fonts are system, icons are inline SVG. */

:root {
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans",
          "Noto Sans Devanagari", sans-serif;
  --radius: 14px;
  --radius-sm: 9px;
  --shadow: 0 6px 24px rgba(0, 20, 8, .25);
  --nav-h: 62px;
  --top-h: 56px;
  /* One spacing scale for every grid and stack, so cards, KPI tiles and rows
     all breathe the same amount instead of each picking their own number. */
  --gap: 12px;
}
@media (min-width: 720px)  { :root { --gap: 14px; } }
@media (min-width: 1024px) { :root { --gap: 18px; } }

/* ── dark (default): deep forest ── */
:root, :root[data-theme="dark"] {
  --bg: #0c1710;
  --bg-grad: radial-gradient(1200px 600px at 85% -10%, rgba(52,168,83,.14), transparent 60%),
             radial-gradient(900px 500px at -10% 110%, rgba(134,217,124,.08), transparent 55%);
  --surface: #13241a;
  --elevated: #1a3123;
  --text: #e7f3ea;
  --muted: #93b09e;
  --primary: #34a853;
  --primary-strong: #46c46a;
  --primary-soft: rgba(52,168,83,.16);
  --on-primary: #ffffff;
  --lime: #8bdc81;
  --danger: #ef6351;
  --danger-soft: rgba(239,99,81,.14);
  --warn: #e2b23c;
  --warn-soft: rgba(226,178,60,.14);
  --border: rgba(139,220,129,.15);
  --input-bg: #0f1d14;
  --shadow: 0 8px 28px rgba(0, 12, 4, .45);

  /* ── Payment-rail hues ──────────────────────────────────────────────────────
     THE STANDARD, shared with the admin panel — see the rationale block in
     config/money_rails.php, which is the source these mirror. A rail is the
     same colour here, on the trends donuts and on the withdrawals console:
       P2P blue · Bank grey · UPI orange · TRC20 green · BEP20 yellow
     These are the DARK steps — lifted so they carry on the dark surface. Rail
     pills always print their NAME, so identity is never colour-alone and the
     tighter separation at these steps is not load-bearing. */
  --rail-p2p:   #60a5fa;
  --rail-bank:  #94a3b8;
  --rail-upi:   #fb923c;
  --rail-qr:    #fb923c;
  --rail-trc20: #4ade80;
  --rail-bep20: #facc15;
  --rail-other: #c084fc;
}

/* ── light: fresh garden ── */
:root[data-theme="light"] {
  --bg: #f1f6f1;
  --bg-grad: radial-gradient(1200px 600px at 85% -10%, rgba(52,168,83,.10), transparent 60%),
             radial-gradient(900px 500px at -10% 110%, rgba(30,142,66,.07), transparent 55%);
  --surface: #ffffff;
  --elevated: #f6faf6;
  --text: #14271b;
  --muted: #5c7465;
  --primary: #1e8e42;
  --primary-strong: #187a37;
  --primary-soft: rgba(30,142,66,.10);
  --on-primary: #ffffff;
  --lime: #3fa15b;
  --danger: #cf3f2d;
  --danger-soft: rgba(207,63,45,.09);
  --warn: #a97b13;
  --warn-soft: rgba(169,123,19,.10);
  --border: #dde9df;
  --input-bg: #ffffff;
  --shadow: 0 6px 22px rgba(20, 60, 32, .10);

  /* Light steps = exactly the admin standard (validated; see money_rails.php). */
  --rail-p2p:   #3b82f6;
  --rail-bank:  #64748b;
  --rail-upi:   #c2410c;
  --rail-qr:    #c2410c;
  --rail-trc20: #15803d;
  --rail-bep20: #ca8a04;
  --rail-other: #7e22ce;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  font-family: var(--font);
  background: var(--bg);
  background-image: var(--bg-grad);
  background-attachment: fixed;
  color: var(--text);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
button { font-family: inherit; }
input, select, textarea { font-family: inherit; font-size: 15px; color: var(--text); }

/* ═══ Login screen + falling leaves ═══ */
.login-wrap {
  min-height: 100dvh;
  display: flex; align-items: center; justify-content: center;
  padding: 24px; position: relative; overflow: hidden;
}
.leaves { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.leaf {
  position: absolute; top: -60px;
  width: 26px; height: 26px; opacity: .8;
  background-repeat: no-repeat; background-size: contain;
  animation: leaf-fall linear infinite, leaf-sway ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes leaf-fall {
  from { transform: translateY(-8vh) rotate(0deg); }
  to   { transform: translateY(115vh) rotate(340deg); }
}
@keyframes leaf-sway {
  from { margin-left: -28px; }
  to   { margin-left: 28px; }
}
@media (prefers-reduced-motion: reduce) { .leaf { animation: none; display: none; } }

.login-card {
  position: relative; z-index: 1;
  width: 100%; max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 20px;
  box-shadow: var(--shadow);
  padding: 30px 26px 26px;
}
.login-logo { display: flex; align-items: center; gap: 10px; justify-content: center; margin-bottom: 6px; }
.login-logo svg { width: 34px; height: 34px; }
.login-logo .name { font-size: 21px; font-weight: 800; letter-spacing: .3px; }
.login-sub { text-align: center; color: var(--muted); font-size: 13px; margin-bottom: 22px; }
.login-toggles { position: absolute; top: 14px; right: 14px; display: flex; gap: 8px; z-index: 2; }

/* ═══ App shell ═══ */
.shell { min-height: 100dvh; display: flex; flex-direction: column; }
.topbar {
  position: sticky; top: 0; z-index: 30;
  height: var(--top-h);
  display: flex; align-items: center; gap: 10px;
  padding: 0 14px;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
.topbar .brand { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 16px; }
.topbar .brand svg { width: 24px; height: 24px; }
.topbar .spacer { flex: 1; }
.content {
  flex: 1; width: 100%; max-width: 1180px; margin: 0 auto;
  padding: var(--gap) 14px calc(var(--nav-h) + 24px);
}

/* bottom nav (mobile) */
.bottomnav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  height: calc(var(--nav-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  display: flex;
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--border);
}
.bottomnav a {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; text-decoration: none; color: var(--muted); font-size: 11px; font-weight: 600;
}
.bottomnav a svg { width: 22px; height: 22px; }
.bottomnav a.active { color: var(--primary-strong); }
.sidebar { display: none; }

/* desktop: sidebar replaces the bottom nav */
@media (min-width: 1024px) {
  .shell { flex-direction: row; }
  .bottomnav { display: none; }
  /* THE SIDEBAR MUST NOT SCROLL WITH THE PAGE.
     It was already `position: sticky; top: 0`, which did nothing: .shell is a
     row flexbox, so the sidebar STRETCHED to the full height of the content
     column. An element taller than the viewport has nothing left to stick with —
     it just scrolls away like any other block. The fix is to stop it stretching
     (align-self) and pin its height to the viewport rather than the content, so
     sticky finally has room to work. A long nav scrolls inside itself. */
  .sidebar {
    display: flex; flex-direction: column; gap: 4px;
    width: 232px; flex: 0 0 auto;
    height: 100dvh; align-self: flex-start; overflow-y: auto;
    position: sticky; top: 0;
    padding: 18px 12px;
    background: color-mix(in srgb, var(--surface) 70%, transparent);
    border-right: 1px solid var(--border);
  }
  .sidebar .brand { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 18px; padding: 6px 10px 18px; }
  .sidebar .brand svg { width: 28px; height: 28px; }
  .sidebar a {
    display: flex; align-items: center; gap: 11px;
    padding: 11px 12px; border-radius: var(--radius-sm);
    color: var(--muted); text-decoration: none; font-weight: 600; font-size: 14px;
  }
  .sidebar a svg { width: 20px; height: 20px; }
  .sidebar a:hover { background: var(--primary-soft); color: var(--text); }
  .sidebar a.active { background: var(--primary-soft); color: var(--primary-strong); }
  .main-col { flex: 1; min-width: 0; display: flex; flex-direction: column; }
  .content { padding: var(--gap) var(--gap) 40px; }
}

/* ═══ Components ═══ */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: var(--gap);
}
.card h3 { font-size: 15px; font-weight: 700; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }
.grid-cards {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: var(--gap); margin-bottom: var(--gap);
}
@media (min-width: 720px) { .grid-cards { grid-template-columns: repeat(4, 1fr); } }
.kpi {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 15px 16px;
}
.kpi .v { font-size: 20px; font-weight: 800; margin-top: 2px; }
.kpi .l { font-size: 12px; color: var(--muted); font-weight: 600; }
.kpi.good .v { color: var(--primary-strong); }
.kpi.bad .v { color: var(--danger); }
.kpi .l { display: flex; align-items: center; gap: 5px; }
/* The one line under "Collected today" that names money this desk did not settle
   itself. Deliberately inside the card: the question it answers is asked while
   looking at that number, not on another page. */
.kpi-sub { margin-top: 7px; font-size: 11.5px; line-height: 1.45; }
.kpi-sub a { color: var(--warn); font-weight: 700; text-decoration: none; }
.kpi-sub a:hover { text-decoration: underline; }
.kpi-sub .hint { vertical-align: middle; margin-left: 4px; }

/* ── hints ──────────────────────────────────────────────────────────────────
   A small "i" beside a label, and one shared bubble positioned in JS (see
   hintShow) so it can escape a 2-column card grid and still stay on screen. */
.hint {
  flex: 0 0 auto; width: 15px; height: 15px; padding: 0; line-height: 13px;
  border-radius: 50%; border: 1px solid var(--border); background: var(--elevated);
  color: var(--muted); font-size: 10px; font-weight: 800; font-family: inherit;
  cursor: pointer; -webkit-appearance: none; appearance: none;
}
.hint:hover, .hint[aria-expanded="true"] {
  color: var(--on-primary); background: var(--primary); border-color: var(--primary);
}
.hint:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.hint-pop {
  position: fixed; z-index: 90; display: none;
  max-width: min(320px, calc(100vw - 16px));
  padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--text); color: var(--surface);
  font-size: 12.5px; font-weight: 500; line-height: 1.5;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .28);
}
.hint-pop.on { display: block; }

/* Who settled a ledger row. `out` = it did not come through this panel. */
.src-tag {
  display: inline-block; padding: 2px 7px; border-radius: 999px;
  font-size: 11px; font-weight: 700; white-space: nowrap;
  background: color-mix(in srgb, var(--primary) 14%, transparent); color: var(--primary-strong);
}
.src-tag.out { background: color-mix(in srgb, var(--warn) 20%, transparent); color: var(--warn); }

/* `display: flex` on a class BEATS the hidden attribute — an element marked
   hidden still renders. Every layout rule below would otherwise silently defeat
   it, so state the attribute's meaning once, globally. */
[hidden] { display: none !important; }

/* Activity drill-down: the custom date range, and the pager under the table. */
.act-range { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: var(--gap); }
.act-range input[type="date"] {
  padding: 8px 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--elevated); color: var(--text);
  font: inherit; font-size: 13px;
}
.act-pager { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }

/* Settlement request form: two columns where there is room, one on a phone. */
.sform { display: grid; grid-template-columns: 1fr; gap: 0 12px; }
@media (min-width: 640px) { .sform { grid-template-columns: 1fr 1fr; } }

/* The wait a payout accumulated BEFORE it reached this desk. Deliberately quiet:
   it explains the number next to it, it is not the desk's own score. */
.pre-wait {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 600; color: var(--muted);
}
.bar i.warn { background: var(--warn); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid var(--border); background: var(--elevated); color: var(--text);
  border-radius: var(--radius-sm); padding: 10px 16px;
  font-size: 14px; font-weight: 700; cursor: pointer;
  transition: filter .15s, transform .05s;
}
.btn:active { transform: scale(.98); }
.btn:hover { filter: brightness(1.08); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-primary { background: var(--primary); border-color: var(--primary); color: var(--on-primary); }
.btn-danger { background: var(--danger-soft); border-color: transparent; color: var(--danger); }
.btn-warn { background: var(--warn-soft); border-color: transparent; color: var(--warn); }
.btn-ghost { background: transparent; }
.btn-sm { padding: 7px 12px; font-size: 13px; border-radius: 8px; }
.btn-block { width: 100%; }
.btn-icon { padding: 8px; border-radius: 10px; line-height: 0; }
.btn-icon svg { width: 19px; height: 19px; }

.field { margin-bottom: 12px; }
.field label { display: block; font-size: 12.5px; font-weight: 700; color: var(--muted); margin-bottom: 6px; }
.field input, .field select, .field textarea {
  width: 100%; padding: 11px 13px;
  background: var(--input-bg); border: 1px solid var(--border);
  border-radius: var(--radius-sm); outline: none;
}
.field input:focus, .field select:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }

/* Password reveal. The button sits inside the field box, so the input reserves
   room for it rather than having text slide underneath. */
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 44px; }
.pw-eye { position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
          background: none; border: 0; padding: 6px; line-height: 0; cursor: pointer;
          color: var(--muted); border-radius: 8px; }
.pw-eye:hover { color: var(--primary); background: var(--primary-soft); }
.pw-eye svg { width: 19px; height: 19px; display: block; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 700; border-radius: 999px; padding: 3px 10px;
}
.pill-green { background: var(--primary-soft); color: var(--primary-strong); }
.pill-red { background: var(--danger-soft); color: var(--danger); }
.pill-amber { background: var(--warn-soft); color: var(--warn); }
.pill-gray { background: color-mix(in srgb, var(--muted) 14%, transparent); color: var(--muted); }

/* toggle switch */
.switch { position: relative; width: 46px; height: 26px; flex: none; cursor: pointer; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .track {
  position: absolute; inset: 0; border-radius: 999px;
  background: color-mix(in srgb, var(--muted) 30%, transparent);
  transition: background .18s;
}
.switch .track::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px; border-radius: 50%;
  background: #fff; transition: transform .18s;
  box-shadow: 0 1px 4px rgba(0,0,0,.3);
}
.switch input:checked + .track { background: var(--primary); }
.switch input:checked + .track::after { transform: translateX(20px); }

/* list rows (mobile) / table-ish (desktop handled by same rows) */
.row-list { display: flex; flex-direction: column; gap: var(--gap); }
.item {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 13px 14px;
  /* Lifts the card off the page so a list of payouts reads as separate pieces
     of work rather than one block of text. Kept soft — a payer scans this list
     for minutes at a time. */
  box-shadow: 0 1px 3px rgba(0,0,0,.07), 0 1px 2px rgba(0,0,0,.04);
}
.item .head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.item .amt { font-size: 18px; font-weight: 800; }
.item .sub { color: var(--muted); font-size: 12.5px; margin-top: 3px; word-break: break-all; }
.item .acts { display: flex; gap: 8px; margin-top: 11px; flex-wrap: wrap; }
.item .acts .btn { flex: 1; min-width: 90px; }
@media (min-width: 720px) {
  .item { display: flex; align-items: center; gap: 14px; }
  .item .body { flex: 1; min-width: 0; }
  .item .acts { margin-top: 0; }
  .item .acts .btn { flex: none; }
}

/* QR card grid */
.qr-grid { display: grid; grid-template-columns: 1fr; gap: var(--gap); }
@media (min-width: 640px) { .qr-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .qr-grid { grid-template-columns: repeat(3, 1fr); } }
.qr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; }
.qr-card .qr-top { display: flex; gap: 12px; }
.qr-card img.qr-img {
  width: 74px; height: 74px; border-radius: 10px; object-fit: cover;
  border: 1px solid var(--border); background: #fff; flex: none;
}
.qr-card .meter {
  height: 6px; border-radius: 4px; margin-top: 10px;
  background: color-mix(in srgb, var(--muted) 16%, transparent); overflow: hidden;
}
.qr-card .meter i { display: block; height: 100%; background: var(--primary); border-radius: 4px; }
.qr-card .meter.hot i { background: var(--warn); }
.qr-card .acts { display: flex; gap: 7px; margin-top: 12px; flex-wrap: wrap; }

/* live-stream indicator */
.live-dot {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: color-mix(in srgb, var(--muted) 45%, transparent);
  transition: background .3s, box-shadow .3s;
}
.live-dot.on { background: var(--primary-strong); box-shadow: 0 0 0 3px var(--primary-soft); animation: pulse 2.4s ease-in-out infinite; }
@keyframes pulse { 50% { box-shadow: 0 0 0 6px transparent; } }
@media (prefers-reduced-motion: reduce) { .live-dot.on { animation: none; } }

/* count badge on a nav icon */
.bottomnav a, .sidebar a { position: relative; }
.nav-badge {
  position: absolute; top: 4px; left: 50%; margin-left: 4px;
  min-width: 17px; height: 17px; padding: 0 4px;
  border-radius: 9px; background: var(--danger); color: #fff;
  font-size: 10.5px; font-weight: 800; line-height: 17px; text-align: center;
}
@media (min-width: 1024px) {
  /* order:3 puts it after the label instead of between icon and text */
  .sidebar .nav-badge { position: static; margin-left: auto; order: 3; }
}

/* ═══ payout destination block ═══
   Built to be transcribed into a banking app: fixed label column so the values
   line up, and monospace figures so digits keep their width. */
.fin { margin-top: 9px; display: flex; flex-direction: column; gap: 4px; }
.fin-row { display: flex; gap: 10px; align-items: baseline; font-size: 13.5px; }
.fin-row .k {
  flex: none; width: 86px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase;
  color: var(--muted);
}
.fin-row .v { min-width: 0; word-break: break-all; }
.fin-row .nm { font-weight: 700; font-size: 14.5px; }
.fin-row .tm { color: var(--muted); }
.fin-row .acct, .fin-row .ifsc {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 15px; font-weight: 700; letter-spacing: .5px;
}
/* Alternating pairs: the eye keeps its place across a 14-digit number and a
   transposed digit breaks the rhythm visibly. */
.fin-row .pr.a { color: var(--text); }
.fin-row .pr.b { color: var(--muted); }
.fin-row .pr + .pr { margin-left: 2px; }
/* Bank code vs branch code — confirm the bank before reading the rest. */
.fin-row .if-a { color: var(--primary-strong); }
.fin-row .if-b { color: var(--muted); }

.pill-method {
  background: color-mix(in srgb, var(--rail, var(--primary)) 20%, transparent);
  color: var(--rail, var(--primary-strong)); font-weight: 800; letter-spacing: .4px;
}
/* The rail a pill belongs to. Set as an attribute by railPill() in app.js, so
   the colour follows the ENTITY and never the row's position in the list. */
.pill-method[data-rail="P2P"]   { --rail: var(--rail-p2p);   }
.pill-method[data-rail="BANK"]  { --rail: var(--rail-bank);  }
.pill-method[data-rail="UPI"]   { --rail: var(--rail-upi);   }
.pill-method[data-rail="TRC20"] { --rail: var(--rail-trc20); }
.pill-method[data-rail="BEP20"] { --rail: var(--rail-bep20); }
.pill-method[data-rail="OTHER"] { --rail: var(--rail-other); }

/* Money-path outage banner. Sits above the queue and stays visible when the queue
   is EMPTY — with the gateway down nothing is routed, so "no rows" is the symptom,
   not the all-clear. Danger-toned because approvals are genuinely blocked. */
.gw-down {
  border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
  background: color-mix(in srgb, var(--danger) 8%, var(--surface));
  border-radius: 12px; padding: 12px 14px; margin-bottom: 12px;
}
.gw-down .gw-t { font-weight: 700; color: var(--danger); margin-bottom: 3px; }
.gw-down .gw-b { font-size: 13px; color: var(--text); opacity: .85; line-height: 1.45; }

/* SLA accent on a queue row — a left edge, so it reads at a glance */
.item.sla-amber { border-left: 4px solid var(--warn); }
/* URGENCY LIVES IN THE LEFT BAR AND THE PILL, NOT THE FILL.
   Tinting the whole card red made every late payout look like an error state,
   and on this queue "late" is the normal condition — it read as noise and
   fought the account details the payer actually has to copy. The surface stays
   white so the beneficiary, account and IFSC keep maximum contrast. */
.item.sla-red { border-left: 4px solid var(--danger); }

/* ═══ chat workspace ═══
   Phone: one pane at a time (list → conversation). Desktop: both side by side. */
.chat-wrap { display: flex; gap: 12px; height: calc(100dvh - var(--top-h) - var(--nav-h) - 34px); }
.chat-list {
  flex: 1; min-width: 0; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
}
.chat-search { padding: 10px; border-bottom: 1px solid var(--border); }
.chat-search input {
  width: 100%; padding: 9px 12px; background: var(--input-bg);
  border: 1px solid var(--border); border-radius: var(--radius-sm); outline: none;
}
#rooms { flex: 1; overflow-y: auto; }
.room {
  width: 100%; text-align: left; padding: 11px 13px; cursor: pointer;
  background: transparent; border: 0; border-bottom: 1px solid var(--border); color: var(--text);
}
.room:hover { background: var(--primary-soft); }
.room.on { background: var(--primary-soft); border-left: 3px solid var(--primary); }
.room-top { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.room-sub { font-size: 12px; color: var(--muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.chat-main {
  flex: 1.4; min-width: 0; display: none; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
}
.chat-wrap.open .chat-list { display: none; }
.chat-wrap.open .chat-main { display: flex; }
.chat-head { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.chat-head .spacer { flex: 1; }
.chat-msgs { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 8px; }
.msg { max-width: 78%; padding: 9px 12px; border-radius: 14px; font-size: 14px; line-height: 1.4; word-break: break-word; }
.msg.in { align-self: flex-start; background: var(--elevated); border-bottom-left-radius: 4px; }
.msg.out { align-self: flex-end; background: var(--primary); color: var(--on-primary); border-bottom-right-radius: 4px; }
.msg-img { max-width: 100%; border-radius: 10px; display: block; margin-bottom: 5px; background: #fff; }
.msg-t { display: block; font-size: 10.5px; opacity: .7; margin-top: 3px; }
.chat-send { display: flex; gap: 8px; padding: 10px; border-top: 1px solid var(--border); }
.chat-send input {
  flex: 1; padding: 10px 13px; background: var(--input-bg);
  border: 1px solid var(--border); border-radius: 999px; outline: none;
}
@media (min-width: 900px) {
  .chat-wrap .chat-list { display: flex !important; max-width: 330px; }
  .chat-main { display: flex; }
  .chat-back { display: none; }
}
@media (min-width: 1024px) { .chat-wrap { height: calc(100dvh - var(--top-h) - 60px); } }

/* tabs + range chips */
/* ── section tabs ───────────────────────────────────────────────────────────
   A real tab bar sharing one baseline, not four boxed buttons. Four bordered
   boxes read as four independent actions — the same weight as "Add account" —
   when they are one control selecting a view. The shared rule plus an underline
   on the active tab says "these belong together, one is current".

   The page below also has CHIPS (Today / 7 days / …). Tabs and chips must not
   look alike: tabs pick the SCREEN, chips filter what is on it. Hence
   underline-on-a-rule here, and filled pills there. */
.tabs {
  display: flex; gap: 2px; margin-bottom: 14px;
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border-bottom: 1px solid var(--border);
  /* Hide the scrollbar: with 4-5 tabs it almost never scrolls, and a visible
     track under the rule reads as a broken border. */
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  flex: 1 0 auto; min-width: 84px; padding: 10px 14px 9px;
  border: 0; background: none; color: var(--muted);
  font-size: 13.5px; font-weight: 700; cursor: pointer; white-space: nowrap;
  /* Reserve the indicator on every tab so switching does not shift the row. */
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color .15s, border-color .15s;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--primary-strong); border-bottom-color: var(--primary); }
.chips { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; }
.chip {
  padding: 6px 13px; border-radius: 999px; border: 1px solid var(--border);
  background: var(--surface); color: var(--muted); font-size: 12.5px; font-weight: 700; cursor: pointer;
}
.chip.active { background: var(--primary); border-color: var(--primary); color: var(--on-primary); }

/* ── payment-checks filter bar ─────────────────────────────────────────────
   Phone first: this screen is worked from a phone, standing up, one-handed.
   The two chip rows SCROLL sideways instead of wrapping into a wall that
   pushes the actual list below the fold — eight periods would otherwise eat
   three rows of a small screen. Above 720px they wrap normally, because there
   the room exists and a scroller you cannot see the end of is worse. */
.inq-filters { margin-bottom: 10px; }
.inq-filters .chips {
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch; margin-bottom: 8px; padding-bottom: 2px;
}
.inq-filters .chips::-webkit-scrollbar { display: none; }
.inq-filters .chip { flex: 0 0 auto; }
@media (min-width: 720px) { .inq-filters .chips { flex-wrap: wrap; overflow-x: visible; } }

.inq-dates { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.inq-dates input {
  flex: 1 1 0; min-width: 0;              /* min-width:0 or the date input refuses to shrink on iOS */
  padding: 9px 10px; border-radius: 9px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font-size: 13px; font-family: inherit;
}
.inq-arrow { color: var(--muted); font-size: 13px; flex: 0 0 auto; }

.inq-search { position: relative; display: flex; align-items: center; }
.inq-search input {
  width: 100%; padding: 10px 34px 10px 34px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  font-size: 16px;                        /* 16px stops iOS Safari zooming the page on focus */
  font-family: inherit;
}
.inq-search input:focus { outline: none; border-color: var(--primary); }
.inq-sic { position: absolute; left: 10px; width: 16px; height: 16px; color: var(--muted); pointer-events: none; }
.inq-sic svg { width: 16px; height: 16px; display: block; }
.inq-clr {
  position: absolute; right: 6px; width: 26px; height: 26px; border: 0; border-radius: 50%;
  background: transparent; color: var(--muted); font-size: 19px; line-height: 1; cursor: pointer;
}

.inq-count { font-size: 12px; color: var(--muted); margin: 0 0 8px 2px; }
/* Facts wrap as whole units — a UTR broken across two lines cannot be read back
   over the phone, which is exactly what these get used for. Separated by space
   rather than a "·": a dot rendered between two inline-blocks ends up orphaned
   at the start of the wrapped line, which on a 390px screen happens constantly. */
.item .sub .inq-f { display: inline-block; word-break: normal; margin-right: 13px; }
.item .sub .inq-f:last-child { margin-right: 0; }
.btn-more { width: 100%; margin-top: var(--gap); }

/* account figure strip */
.acct-figs { display: flex; gap: 14px; margin-top: 10px; flex-wrap: wrap; }
.acct-figs > div { display: flex; flex-direction: column; }
.acct-figs span { font-size: 11.5px; color: var(--muted); font-weight: 600; }
.acct-figs b { font-size: 15px; }

/* horizontal bars */
.bar-row { display: grid; grid-template-columns: minmax(70px, 1fr) 2fr auto; gap: 10px; align-items: center; margin-bottom: 8px; font-size: 13px; }
.bar { height: 8px; border-radius: 5px; background: color-mix(in srgb, var(--muted) 16%, transparent); overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--primary); border-radius: 5px; }

/* tables — always scroll inside their own box, never the page */
.tbl-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl th, .tbl td { padding: 9px 10px; text-align: left; border-bottom: 1px solid var(--border); white-space: nowrap; }
.tbl th { color: var(--muted); font-weight: 700; font-size: 11.5px; text-transform: uppercase; letter-spacing: .3px; }
.tbl tr:last-child td { border-bottom: 0; }

.empty { text-align: center; color: var(--muted); padding: 38px 12px; font-size: 14px; }
.empty svg { width: 42px; height: 42px; opacity: .5; margin-bottom: 8px; }

.section-title { display: flex; align-items: center; justify-content: space-between; margin: 4px 2px 12px; }
.section-title h2 { font-size: 18px; font-weight: 800; }

.otp-box { text-align: center; }
.otp-box img { border-radius: 12px; background: #fff; padding: 6px; margin: 10px 0; }
.otp-secret { font-family: ui-monospace, monospace; background: var(--input-bg); border: 1px dashed var(--border);
  border-radius: 8px; padding: 8px 10px; font-size: 13px; word-break: break-all; margin: 8px 0; }
.code-input { letter-spacing: 8px; text-align: center; font-size: 22px !important; font-weight: 800; }

.onetime-pw {
  background: var(--primary-soft); border: 1px dashed var(--primary);
  border-radius: var(--radius-sm); padding: 12px; margin: 10px 0;
  font-size: 14px; text-align: center;
}
.onetime-pw b { font-family: ui-monospace, monospace; font-size: 17px; letter-spacing: 1px; }

/* advisory banner — same shape as onetime-pw but prose, not a credential */
.notice {
  background: var(--warn-soft); border: 1px dashed var(--warn);
  border-radius: var(--radius-sm); padding: 12px 14px; margin: 0 0 14px;
  font-size: 14px; line-height: 1.45;
}
.notice b { display: block; margin-bottom: 3px; }
.notice .sub { font-size: 12.5px; opacity: .85; }

/* toast */
#toast-root { position: fixed; left: 0; right: 0; bottom: calc(var(--nav-h) + 18px); z-index: 130;
  display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none; }
@media (min-width: 1024px) { #toast-root { bottom: 26px; } }
.toast {
  background: var(--elevated); color: var(--text);
  border: 1px solid var(--border); border-left: 4px solid var(--primary);
  border-radius: 10px; box-shadow: var(--shadow);
  padding: 11px 16px; font-size: 14px; font-weight: 600; max-width: 92vw;
  animation: toast-in .22s ease;
}
.toast.err { border-left-color: var(--danger); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }

/* modal (bottom sheet on mobile, dialog on desktop) */
.modal-back { position: fixed; inset: 0; background: rgba(4, 12, 6, .55); z-index: 80;
  display: flex; align-items: flex-end; justify-content: center; }
.modal { background: var(--surface); border: 1px solid var(--border);
  border-radius: 18px 18px 0 0; width: 100%; max-width: 560px; max-height: 88dvh;
  overflow: auto; padding: 20px 18px calc(18px + env(safe-area-inset-bottom));
  animation: sheet-up .22s ease; }
@keyframes sheet-up { from { transform: translateY(30px); opacity: .6; } }
@media (min-width: 720px) {
  .modal-back { align-items: center; }
  .modal { border-radius: 18px; padding: 22px; }
}
.modal h3 { font-size: 16px; font-weight: 800; margin-bottom: 14px; }

.skel { border-radius: var(--radius); background:
  linear-gradient(100deg, var(--surface) 40%, var(--elevated) 50%, var(--surface) 60%);
  background-size: 200% 100%; animation: skel 1.1s infinite linear; height: 74px; margin-bottom: 10px; }
@keyframes skel { to { background-position: -200% 0; } }
.muted { color: var(--muted); }
.mono { font-family: ui-monospace, monospace; }
.mt8 { margin-top: 8px; } .mt14 { margin-top: 14px; }

/* conflict evidence thumbnails */
.cf-thumb {
  width: 54px; height: 54px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--border); background: #fff; cursor: pointer;
}

/* collapsible setup steps in the alerts card */
.tg-steps { margin-bottom: 12px; }
.tg-steps summary { cursor: pointer; font-size: 13px; font-weight: 700; color: var(--primary-strong); }
.tg-steps .sub { font-size: 12.5px; color: var(--muted); margin-top: 6px; line-height: 1.6; }

/* ═══ evidence strip + full-screen viewer ═══ */
.ev { display: flex; gap: 10px; align-items: flex-start; margin-top: 9px; }
.ev-k {
  flex: none; width: 86px; padding-top: 4px;
  font-size: 10.5px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase;
  color: var(--muted);
}
.ev-row { display: flex; gap: 6px; flex-wrap: wrap; min-width: 0; }
.ev-th {
  width: 52px; height: 52px; object-fit: cover; cursor: zoom-in;
  border-radius: 8px; border: 1px solid var(--border); background: #fff;
  transition: transform .12s;
}
.ev-th:hover { transform: scale(1.06); }

.lb {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(3, 10, 5, .92);
  display: flex; align-items: center; justify-content: center;
  padding: 56px 16px;
}
.lb-img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; border-radius: 10px; background: #fff;
}
.lb-x, .lb-nav {
  position: absolute; border: 0; cursor: pointer; color: #fff;
  background: rgba(255, 255, 255, .12); backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
}
.lb-x { top: 14px; right: 14px; width: 40px; height: 40px; border-radius: 50%; font-size: 26px; line-height: 1; }
.lb-nav { top: 50%; transform: translateY(-50%); width: 46px; height: 66px; border-radius: 10px; font-size: 34px; line-height: 1; }
.lb-prev { left: 10px; } .lb-next { right: 10px; }
.lb-x:hover, .lb-nav:hover { background: rgba(255, 255, 255, .22); }
.lb-count {
  position: absolute; bottom: 18px; left: 50%; transform: translateX(-50%);
  color: #fff; background: rgba(0, 0, 0, .45); backdrop-filter: blur(6px);
  padding: 5px 14px; border-radius: 999px; font-size: 13px; font-weight: 700;
}
@media (min-width: 900px) { .lb-prev { left: 26px; } .lb-next { right: 26px; } }

/* Admin-impersonation banner: an admin looking at a manager's desk must never
   be mistaken for the manager working it. */
.imp-bar {
  background: var(--warn-soft); color: var(--warn);
  border-bottom: 1px solid var(--warn);
  padding: 8px 14px; font-size: 12.5px; font-weight: 700; text-align: center;
}

/* team: QR chips + sign-in history */
.qr-chip {
  display: inline-flex; align-items: center; gap: 6px; cursor: zoom-in;
  background: var(--elevated); border: 1px solid var(--border);
  border-radius: 999px; padding: 3px 10px 3px 3px; font-size: 12.5px; font-weight: 600;
}
.qr-chip img { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; background: #fff; }
.qr-chip:hover { border-color: var(--primary); }
.sig { margin-top: 9px; }
.sig summary { cursor: pointer; font-size: 12.5px; font-weight: 700; color: var(--primary-strong); }
.sig .tbl { margin-top: 6px; }
.card h3 { align-items: center; }

/* Network-off notice: a manager must never think their desk is live when the
   owner has not switched the network on. */
.net-bar { background: color-mix(in srgb, var(--muted) 14%, transparent); color: var(--muted); border-bottom-color: var(--border); }

/* ═══ bottom sheet (process drawer) ═════════════════════════════════════════
   Enters from the bottom and caps at 92vh so the sheet itself scrolls rather
   than the page behind it — on a phone with the keyboard up, a page that
   scrolls under a fixed sheet loses the field you are typing into. */
.drawer-back {
  /* ── OVERLAY STACK (keep these in one place) ────────────────────────────
       30  topbar / bottom nav
       80  modal
       95  search overlay (blurs everything under it)
      100  bottom sheet  ← ABOVE search: search RESULTS render into this sheet,
                           so at 90 they opened underneath the search blur
      120  lightbox
      130  toasts        ← above all of it: a toast confirms an action taken in
                           any layer, so it must never be the thing that is
                           covered
     ─────────────────────────────────────────────────────────────────────── */
  position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,.45);
  display: flex; align-items: flex-end; justify-content: center;
  opacity: 0; transition: opacity .16s ease;
}
.drawer-back.open { opacity: 1; }
/* Opened FROM search: the page behind is already blurred and dimmed by the
   search overlay, so the sheet drops its own scrim. Stacking a second one made
   the search bar — still the active control — nearly unreadable, and the two
   dims together read as a bug. Taps outside the sheet still reach the search
   backdrop underneath, which closes both. */
body.sx-open .drawer-back { background: transparent; pointer-events: none; }
body.sx-open .drawer { pointer-events: auto; }
.drawer {
  width: 100%; max-width: 560px; max-height: 92vh; overflow-y: auto;
  background: var(--surface); color: var(--text);
  border-radius: 18px 18px 0 0; padding: 14px 16px 22px;
  box-shadow: 0 -8px 30px rgba(0,0,0,.28);
  transform: translateY(14px); transition: transform .18s ease;
}
.drawer-back.open .drawer { transform: translateY(0); }
/* The grab bar is affordance only — the sheet is closed by the backdrop or the
   Cancel button, so it is not a drag target and carries no handler. */
.dw-grab { width: 40px; height: 4px; border-radius: 3px; background: var(--border);
           margin: 0 auto 12px; }

.pd-qr { display: flex; flex-direction: column; align-items: center; gap: 8px;
         padding: 14px; background: #fff; border: 1px solid var(--border);
         border-radius: 12px; margin-bottom: 12px; }
/* White plate under the QR regardless of theme: a dark-mode QR does not scan. */
.pd-qr-img { width: 220px; height: 220px; image-rendering: pixelated; }
.pd-vpa { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12.5px;
          color: #374151; word-break: break-all; text-align: center; }
.pd-warn { font-size: 12px; margin-top: 6px; min-height: 16px; color: var(--warn); }
.pd-thumb-img { max-width: 120px; border-radius: 8px; margin-top: 8px;
                border: 1px solid var(--border); }
.fin-row .v.vpa { font-family: ui-monospace, Menlo, Consolas, monospace;
                  word-break: break-all; }

/* ═══ withdrawal pool ═══════════════════════════════════════════════════════ */
.wp-item { display: flex; align-items: center; gap: 12px; }
.wp-item .body { flex: 1; min-width: 0; }
/* The toggle sits on the head row beside the name, so the row keeps one
   baseline instead of the switch riding high against the text. */
.wp-sw { margin-right: 2px; }
.wp-item .head { align-items: center; }
.wp-share { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.wp-share label { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
/* Stepper. Segmented so the two buttons and the value read as ONE control —
   three separate boxes would compete with the toggle on the same row. */
.wp-step {
  display: inline-flex; align-items: stretch;
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden;
  background: var(--surface);
}
.wp-b {
  border: 0; background: none; color: var(--text);
  /* 34px keeps the tap target usable one-handed without making the control
     wider than the name beside it. */
  width: 34px; min-height: 34px; font-size: 17px; font-weight: 700; cursor: pointer;
  line-height: 1; transition: background .12s;
}
.wp-b:hover { background: var(--elevated); }
.wp-b:active { background: var(--primary-soft); }
.wp-n {
  min-width: 32px; display: inline-flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 14px;
  border-left: 1px solid var(--border); border-right: 1px solid var(--border);
}
/* 0 means paused, not "none" — muting it says so without a second label. */
.wp-n.zero { color: var(--muted); }
.wp-hint { font-size: 12px; margin-top: 12px; text-align: center; }
.wp-hint.bad { color: var(--danger); }

/* ═══ More: tile grid ═══════════════════════════════════════════════════════
   Grid rather than flex-wrap so every tile is the same size by construction.
   The old row sized each button to its own text, so "My QRs" wrapped to two
   lines and stood taller than the rest. */
.tiles {
  display: grid; gap: 9px;
  grid-template-columns: repeat(auto-fit, minmax(94px, 1fr));
}
.tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; min-height: 84px; padding: 12px 8px;
  border: 1px solid var(--border); background: var(--elevated); color: var(--text);
  border-radius: var(--radius-sm); cursor: pointer;
  transition: filter .15s, transform .05s, border-color .15s;
}
.tile:hover { filter: brightness(1.06); border-color: var(--primary); }
.tile:active { transform: scale(.97); }
/* THE ACTUAL BUG THIS FIXES: nothing sized an <svg> inside a .btn, so these
   icons rendered unconstrained and collapsed — only the QR one showed. Every
   other context in this stylesheet (.bottomnav a svg, .btn-icon svg) sizes its
   icon explicitly; this row never did. */
.tile .ti { display: flex; align-items: center; justify-content: center; height: 24px; color: var(--primary); }
.tile .ti svg { width: 22px; height: 22px; }
.tile .tl {
  font-size: 12.5px; font-weight: 700; line-height: 1.25; text-align: center;
  /* Two lines max, so a long translation (Hindi runs longer) wraps instead of
     stretching the row — the grid keeps every cell the same height either way. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* ═══ search overlay ════════════════════════════════════════════════════════
   The backdrop blurs the app rather than dimming it: the payer is still
   oriented by the shapes behind, but nothing back there is readable enough to
   compete with the field they are typing into. */
.sx-back {
  position: fixed; inset: 0; z-index: 95;
  background: rgba(8, 20, 14, .48);
  backdrop-filter: blur(7px) saturate(.9); -webkit-backdrop-filter: blur(7px) saturate(.9);
  display: flex; flex-direction: column; align-items: center;
  padding: 68px 14px 0; opacity: 0; transition: opacity .16s ease;
}
.sx-back.open { opacity: 1; }
.sx-bar {
  width: 100%; max-width: 560px; display: flex; align-items: center; gap: 8px;
  background: var(--surface); border: 1px solid var(--primary);
  border-radius: 14px; padding: 10px 12px;
  /* The glow marks this as the active surface while everything behind is
     blurred — without it the bar reads as just another card. */
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 22%, transparent),
              0 12px 34px rgba(0,0,0,.32);
  transform: translateY(-6px); transition: transform .18s ease;
}
.sx-back.open .sx-bar { transform: translateY(0); }
.sx-ic { display: flex; color: var(--primary); }
.sx-ic svg { width: 20px; height: 20px; }
.sx-bar input#sx-q {
  flex: 1; min-width: 0; border: 0; background: none; color: var(--text);
  font-size: 15.5px; font-weight: 600; outline: none; padding: 4px 0;
}
/* ICON ONLY — and the icon is OURS.
   A native date input renders "dd-mm-yyyy" beside its picker button, which ate
   a third of the bar to say what the icon already says. Hiding that text needs
   `color: transparent`, and Chrome paints its calendar glyph with the SAME
   colour — so the icon disappeared along with the text. Fix: draw the icon,
   and lay the real input over it at opacity 0. The OS picker still opens (far
   better than a hand-rolled calendar on a phone) and the visuals are ours. */
.sx-cal {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 34px; flex: none;
  border: 1px solid var(--border); background: var(--elevated);
  border-radius: 9px; cursor: pointer; transition: border-color .15s, background .15s;
}
.sx-cal:hover { border-color: var(--primary); }
.sx-cal-ic { display: flex; color: var(--muted); pointer-events: none; }
.sx-cal-ic svg { width: 18px; height: 18px; }
.sx-cal input#sx-day {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; border: 0; padding: 0; margin: 0;
}
/* A chosen date must be visible or the filter is silently on. */
.sx-cal.has { border-color: var(--primary); background: var(--primary-soft); }
.sx-cal.has .sx-cal-ic { color: var(--primary-strong); }
.sx-x { border: 0; background: none; color: var(--muted); font-size: 22px;
        line-height: 1; cursor: pointer; padding: 0 2px; }
.sx-hint { color: rgba(255,255,255,.82); font-size: 12px; margin-top: 10px; text-align: center; }

.sx-grp { margin-bottom: 14px; }
.sx-grp-h { font-size: 11px; font-weight: 800; text-transform: uppercase;
            letter-spacing: .5px; color: var(--muted); margin: 0 0 7px; }
.sx-n { color: var(--primary-strong); }
.sx-row {
  display: block; width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: 7px;
}
.sx-row:hover { border-color: var(--primary); }
.sx-t { font-size: 14px; font-weight: 700; display: flex; gap: 8px;
        align-items: baseline; flex-wrap: wrap; }
.sx-badge { font-family: ui-monospace, Menlo, Consolas, monospace;
            font-size: 11px; font-weight: 600; color: var(--muted); }
.sx-s { font-size: 11.5px; color: var(--muted); margin-top: 3px; word-break: break-all; }
.sx-nav .sx-t { color: var(--primary-strong); }
.sx-none { text-align: center; color: var(--muted); padding: 26px 10px; font-size: 13.5px; }
/* A reference that is already credited more than once. Loud on purpose: this is
   the one line that stops a manager honouring the same payment twice. */
.sx-warn { margin-top: 6px; font-size: 11.5px; font-weight: 700; line-height: 1.35;
           color: var(--danger); background: var(--danger-soft);
           border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
           border-radius: 6px;
           padding: 6px 8px; text-align: left; white-space: normal; }
.sx-warn-big { margin-top: 12px; font-size: 13px; padding: 10px 12px; }
/* Says out loud what is deliberately absent, so nobody asks the manager to go
   and find a name or a balance in here. */
.sx-priv { font-size: 11.5px; color: var(--muted); text-align: center; margin-top: 12px; }
