:root {
  color-scheme: light;
  --surface-1: #fcfcfb;
  --page: #f9f9f7;
  --text-primary: #0b0b0b;
  --text-secondary: #52514e;
  --muted: #898781;
  --grid: #e1e0d9;
  --baseline: #c3c2b7;
  --border: rgba(11,11,11,0.10);
  --series-1: #2a78d6;
  --series-2: #eb6834;
  --good: #0ca30c;
  --critical: #d03b3b;
  --chip-e: #2a78d6;
  --chip-s: #eb6834;
  --chip-h: #1baf7a;
  --chip-x: #898781;
}
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --surface-1: #1a1a19;
    --page: #0d0d0d;
    --text-primary: #ffffff;
    --text-secondary: #c3c2b7;
    --muted: #898781;
    --grid: #2c2c2a;
    --baseline: #383835;
    --border: rgba(255,255,255,0.10);
    --series-1: #3987e5;
    --series-2: #d95926;
    --chip-e: #3987e5;
    --chip-s: #d95926;
    --chip-h: #199e70;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --surface-1: #1a1a19; --page: #0d0d0d; --text-primary: #ffffff; --text-secondary: #c3c2b7;
  --grid: #2c2c2a; --baseline: #383835; --border: rgba(255,255,255,0.10);
  --series-1: #3987e5; --series-2: #d95926; --chip-e: #3987e5; --chip-s: #d95926; --chip-h: #199e70;
}

* { box-sizing: border-box; }
body { margin: 0; background: var(--page); color: var(--text-primary);
  font: 14px/1.45 system-ui, -apple-system, "Segoe UI", sans-serif; }
header { display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 10px 20px; border-bottom: 1px solid var(--border); background: var(--surface-1);
  position: sticky; top: 0; z-index: 6; flex-wrap: wrap; }   /* above the row panel, which slides under it */
.brand { font-weight: 700; font-size: 16px; }
/* edit lock: view-only hides every editing affordance; source links (a.rbtn) and indicators stay */
/* Admin switch, matching the videoviewer dot: deliberately unlabelled, with no pointer cursor
   and no tooltip, so there is nothing about it to notice. That discretion matters more now the
   page is served with no login at all. Green while view-only, amber once admin mode is on. */
.brand .dot { display: inline-block; position: relative; width: 9px; height: 9px;
  border-radius: 50%; background: var(--good); box-shadow: 0 0 8px var(--good);
  user-select: none; margin-right: 8px; vertical-align: middle; }
body:not(.locked) .brand .dot { background: var(--series-2); box-shadow: 0 0 8px var(--series-2); }
/* a 9px target is unhittable on a phone; this enlarges the tap area without changing the look */
.brand .dot::before { content: ""; position: absolute; inset: -13px; }
body.locked .lgrip, body.locked button.rbtn { display: none !important; }
/* the chip keeps pointer events when locked so hover-to-trace still works; delLink() guards the click */
body.locked #recon-svg path { pointer-events: none; }
body.locked .linkchip { cursor: default; }
/* the ONE edit affordance that survives view-only: anyone with access may mark an item settled */
body.locked button.rbtn.settle-btn { display: inline-block !important; }
/* .src-btn opens the read-only source viewer, so it stays visible like the <a> source links do */
body.locked button.rbtn.src-btn { display: inline-block !important; }
/* the hop out of the placeholder is navigation, not editing: it changes nothing, and hiding it in
   view-only left the placeholder with no way back to the item you came from */
body.locked button.rbtn.jumpback { display: inline-block !important; }
/* a note says what a charge was REALLY for. It moves no money and no total, and it is how the
   view-only side answers back, so it stays. The API mirrors this in OPEN_WRITES. */
body.locked button.rbtn.note-btn { display: inline-block !important; }
/* The panel renders every control in both modes; here is where view-only decides what survives.
   Hiding the row and not just the button keeps a description from sitting under nothing.
   Source links (<a>, .act-srclink) never needed hiding: they only open the document. */
body.locked .rpx-act { display: none; }
body.locked .rpx-act.act-srclink,
body.locked .rpx-act.act-settle-btn,
body.locked .rpx-act.act-src-btn,
body.locked .rpx-act.act-ent-btn,
body.locked .rpx-act.act-note-btn,
body.locked .rpx-act.act-proof-btn { display: grid; }
/* Posting and withdrawing your own note are the whole point of the discussion: a conversation only
   works if the other side can speak. The API mirrors this (/api/note in OPEN_WRITES), and every
   note carries the author the SERVER resolved, so nothing here can be posted anonymously. */
body.locked button.rbtn.nt-post,
body.locked button.rbtn.nt-del { display: inline-block !important; }
/* opening the proof reader changes nothing at all: it is the same kind of control as the source
   document buttons, and the person who filed the expense is usually the one in view-only */
body.locked button.rbtn.proof-btn { display: inline-block !important; }
/* The preview bar's own controls. A preview puts the body in view-only, which hid the only way OUT
   of the preview along with everything else: "leave the preview" and the dismiss X both vanished. */
body.locked #viewbar button.rbtn { display: inline-block !important; }
/* if view-only hid every control on a row, drop the divider too rather than leave an empty rule */
body.locked .rpx-acts:not(:has(.rpx-act.act-srclink, .rpx-act.act-settle-btn,
  .rpx-act.act-src-btn, .rpx-act.act-ent-btn, .rpx-act.act-note-btn,
  .rpx-act.act-proof-btn)) { display: none; }
/* ack is the manager's review queue, so it never appears in view-only */
.ack-btn { background: #b45309; border-color: #b45309; color: #fff; font-weight: 600; }
tr.r-unacked td:first-child { box-shadow: inset 3px 0 0 #b45309; }
#ackall { border: 1px solid #b45309; background: #b45309; color: #fff; border-radius: 999px;
  padding: 4px 12px; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600; }
#ackall[hidden] { display: none !important; }
#lockoutbtn { border: 1px solid var(--border); background: var(--page); color: var(--text-secondary);
  border-radius: 999px; padding: 4px 12px; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600; }
#lockoutbtn.lo-banned { background: var(--critical); border-color: var(--critical); color: #fff; }
#lockoutbtn[hidden] { display: none !important; }
#lockout-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#lockout-backdrop[hidden] { display: none !important; }
#lockout-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(720px, 96vw); max-height: 88vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#lockout-modal h3 { margin: 0 0 6px; }
#lo-table { width: 100%; border-collapse: collapse; margin: 12px 0 6px; font-size: 12.5px; }
#lo-table th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); border-bottom: 1px solid var(--border); padding: 4px 6px; }
#lo-table td { padding: 6px; border-bottom: 1px solid var(--grid); }
#lo-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
#lo-table tr.lo-row-banned td { background: color-mix(in srgb, var(--critical) 12%, var(--surface-1)); }
.lo-b { color: var(--critical); font-weight: 700; }
/* explains the narrowed Ethan column; only meaningful while view-only */
body:not(.locked) .viewnote { display: none; }
.viewnote { margin-top: 4px; font-weight: 400; font-size: 11.5px; line-height: 1.35;
  color: var(--muted); }
.brand .sub { font-weight: 400; color: var(--text-secondary); font-size: 13px; margin-left: 8px; }
nav { display: flex; gap: 6px; }
nav button { background: none; border: 1px solid transparent; color: var(--text-secondary);
  padding: 6px 12px; border-radius: 8px; cursor: pointer; font: inherit; }
nav button.active { color: var(--text-primary); border-color: var(--border); background: var(--page); font-weight: 600; }
main { max-width: 1200px; margin: 0 auto; padding: 16px 20px 60px; }
.tab { display: none; }
.tab.active { display: block; }
.panel { background: var(--surface-1); border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 16px; margin: 14px 0; overflow-x: auto; }
h2 { font-size: 14px; margin: 2px 0 10px; }
.hint { color: var(--muted); font-weight: 400; font-size: 12px; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; margin-top: 14px; }
.card { background: var(--surface-1); border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; }
.card .label { color: var(--text-secondary); font-size: 12px; }
.card .value { font-size: 28px; font-weight: 700; margin: 4px 0; }
.card .value.owed { color: var(--critical); }
.card ul { margin: 6px 0 0; padding-left: 18px; color: var(--text-secondary); font-size: 12px; }
.card .detail { color: var(--muted); font-size: 12px; margin-top: 6px; }

table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
th { text-align: left; color: var(--muted); font-weight: 600; font-size: 12px;
  border-bottom: 1px solid var(--baseline); padding: 6px 8px; white-space: nowrap; }
td { padding: 5px 8px; border-bottom: 1px solid var(--grid); vertical-align: top; }
td.num { text-align: right; white-space: nowrap; }
td.neg { color: var(--critical); }
tr:hover td { background: color-mix(in srgb, var(--text-primary) 4%, transparent); }
a { color: var(--series-1); text-decoration: none; }
a:hover { text-decoration: underline; }

.chip { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600;
  color: #fff; cursor: pointer; border: none; margin-right: 3px; }
.chip.e { background: var(--chip-e); } .chip.s { background: var(--chip-s); }
.chip.h { background: var(--chip-h); } .chip.x { background: var(--chip-x); }
.chip.ghost { background: transparent; color: var(--text-secondary); border: 1px solid var(--border); }
.chip.suggest { background: transparent; color: var(--chip-h); border: 1px dashed var(--chip-h); }
.flagchip { display: inline-block; padding: 1px 7px; border-radius: 999px; font-size: 11px;
  background: color-mix(in srgb, var(--critical) 12%, transparent); color: var(--critical); }
.okchip { color: var(--good); font-weight: 700; }

.filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 10px; }
.filters input, .filters select { background: var(--page); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px; font: inherit; }
.filters button, .pager button { background: var(--series-1); color: #fff; border: none;
  border-radius: 8px; padding: 6px 12px; cursor: pointer; font: inherit; }
.pager { display: flex; gap: 10px; align-items: center; margin-top: 10px; }
.pager button { background: var(--page); color: var(--text-primary); border: 1px solid var(--border); }

#chart-claims svg { display: block; width: 100%; height: auto; }
.legend { display: flex; gap: 16px; margin-top: 8px; font-size: 12px; color: var(--text-secondary); }
.legend .key { display: inline-flex; align-items: center; gap: 6px; }
.legend .swatch { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

.tooltip { position: fixed; pointer-events: none; background: var(--surface-1); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; font-size: 12px;
  box-shadow: 0 4px 14px rgba(0,0,0,.18); z-index: 20; }
.tooltip .tt-title { font-weight: 600; }
.tooltip .tt-row { color: var(--text-secondary); }
ul#flags li { margin: 4px 0; color: var(--text-secondary); }
ul#flags b { color: var(--text-primary); }


/* ---------- mobile (card rows, big touch targets) ---------- */
@media (max-width: 720px) {
  header { padding: 8px 12px; gap: 8px; }
  .brand .sub { display: none; }
  nav { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }
  nav button { white-space: nowrap; padding: 8px 12px; }
  main { padding: 10px 10px 40px; }
  .panel { padding: 10px 12px; }
  .cards { grid-template-columns: 1fr; }
  .card .value { font-size: 24px; }

  .filters { flex-direction: column; align-items: stretch; }
  .filters input, .filters select, .filters button { width: 100%; padding: 10px; }

  .chip { padding: 8px 14px; font-size: 13px; margin: 2px 4px 2px 0; }
  .pager button { padding: 10px 16px; }

  /* tables with data-l cells become stacked cards */
  #txns, #claims, #reimbs { display: block; }
  #txns thead, #claims thead, #reimbs thead,
  #txns th, #claims th, #reimbs th { display: none; }
  #txns tbody, #claims tbody, #reimbs tbody { display: block; }
  #txns tr, #claims tr, #reimbs tr { display: block; border: 1px solid var(--grid);
    border-radius: 10px; margin: 8px 0; padding: 8px 10px; }
  #txns td, #claims td, #reimbs td { display: inline-block; border: none; padding: 2px 10px 2px 0; }
  #txns td[data-l]::before, #claims td[data-l]::before, #reimbs td[data-l]::before {
    content: attr(data-l) " "; color: var(--muted); font-size: 11px; }
  #txns td.prime, #claims td.prime, #reimbs td.prime { display: block; font-weight: 600; padding: 2px 0; }
  #txns td.prime::before, #claims td.prime::before, #reimbs td.prime::before { content: ""; }
  #txns td.chipcell, #claims td.chipcell { display: block; padding: 6px 0 2px; }
  #txns td.chipcell::before, #claims td.chipcell::before { content: ""; }
  #txns td.num, #claims td.num, #reimbs td.num { font-weight: 700; }
  #txns td:empty, #claims td:empty, #reimbs td:empty { display: none; }
}
@media (pointer: coarse) {
  .chip { padding: 8px 14px; font-size: 13px; }
}

/* ---------- reconciliation workspace ---------- */
:root {
  --mark-orange-bg: color-mix(in srgb, #eb6834 18%, var(--surface-1));
  --mark-yellow-bg: color-mix(in srgb, #eda100 16%, var(--surface-1));
  --mark-purple: #8b5cf6;
  --link-line: color-mix(in srgb, var(--series-1) 70%, transparent);
  /* evidence links into her own bank records: deliberately NOT the blue payment-link colour */
  --rec-line: #0d9488;
  /* one payment spread over many claims, and the settlement it can end in */
  --many-line: #2f9e5e;
  --settle-line: #7c3aed;
  /* a reimbursement being spread, as opposed to a link drawn by hand */
  --pay-line: #db2777;
}
:root[data-theme="dark"], :root:where(:not([data-theme="light"])) {
  --mark-orange-bg: color-mix(in srgb, #d95926 26%, var(--surface-1));
  --mark-yellow-bg: color-mix(in srgb, #c98500 22%, var(--surface-1));
  --rec-line: #2dd4bf;   /* lifted for contrast on the dark page */
  --many-line: #4ade80;  /* both lifted for the same reason */
  --settle-line: #a78bfa;
  --pay-line: #f472b6;
}
.recon-toolbar { display: flex; flex-direction: column; gap: 8px; }
/* row-marks legend + color tags live inside the floating account key */
#acct-key-body .lg { display: block; margin: 2px 0; color: var(--text-secondary); }
/* one colour per line: the names are sentences, so a wrapped inline row was unreadable */
#acct-key-body #color-legend { display: flex; flex-direction: column; align-items: stretch; gap: 3px; }
.lg::before { content: ""; display: inline-block; width: 12px; height: 12px; border-radius: 3px;
  margin-right: 5px; vertical-align: -2px; }
.lg-orange::before { background: var(--mark-orange-bg); border: 1px solid #eb6834; }
.lg-yellow::before { background: var(--mark-yellow-bg); border: 1px solid #eda100; }
.lg-red::before { background: transparent; border: 2px solid var(--critical); }
.lg-purple::before { background: var(--mark-purple); border: 1px solid var(--mark-purple); }
.lg-line::before { background: linear-gradient(90deg, transparent 45%, var(--link-line) 45%, var(--link-line) 55%, transparent 55%); border: none; }
.lg-amber::before { background: #b45309; border: 1px solid #b45309; }
.lg-full::before { background: color-mix(in srgb, #b45309 20%, var(--surface-1)); border: 2px solid #b45309; }
.lg-rec::before { background: linear-gradient(90deg, transparent 45%, var(--rec-line) 45%, var(--rec-line) 55%, transparent 55%); border: none; }
.lg-many::before { background: var(--many-line); border: none; }
.lg-pay::before { background: var(--pay-line); border: none; }
.lg-offset::before { background: var(--settle-line); border: none; }
.lg-settle::before { background: var(--settle-line); border: none; }
.lg-hover::before { background: linear-gradient(90deg, var(--link-line) 0 3px, transparent 3px 6px) repeat-x center/6px 3px; border: none; }
.lg-cust::before { background: color-mix(in srgb, var(--rec-line) 22%, var(--surface-1)); border: 1px solid var(--rec-line); }
.recon-controls { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; font-size: 13px; }

/* Room below the last month so the row panel, which always opens downward, can be brought fully
   into view for even the final line item by scrolling it up. Without it the last rows could only
   ever show a panel that ran under the tally bar. */
#recon-wrap { position: relative; padding-bottom: 62vh; }
/* z-order, bottom to top: line items < connector lines (1) < pinned month bars (2) < row panel (4)
   < column headrow (5) < page header (6) < tally bar (7).
   The lines used to sit on top of the grid so a link was never hidden, but a line running up the
   page then crossed every month bar it passed. They now tuck behind the bars, like the rows they
   join, and the hard clip below still stops them reaching the column headers. */
#recon-svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; }
#recon-svg path { pointer-events: stroke; cursor: pointer; }
/* opaque: the 40px column gap would otherwise let pinned month bars show through as they scroll under */
.recon-headrow { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; position: sticky;
  top: var(--header-h, 52px); z-index: 5; background: var(--page); padding-bottom: 6px; }
.recon-headcol { background: var(--surface-1); border: 1px solid var(--border); border-radius: 10px;
  padding: 8px 12px; font-weight: 700; text-align: center; }
.recon-month { margin: 14px 0 22px; }
.recon-month > h3 { margin: 6px 0; font-size: 15px; border-bottom: 1px solid var(--baseline); padding-bottom: 4px; }
.recon-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: start; }
.recon-pane { background: var(--surface-1); border: 1px solid var(--border); border-radius: 12px;
  padding: 8px 10px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain; scrollbar-width: thin; }
.recon-pane .empty { color: var(--muted); font-size: 12px; padding: 10px; text-align: center; }
.recon-pane table { width: 100%; }
.recon-pane th { font-size: 11px; }
.recon-pane td { font-size: 12.5px; padding: 4px 6px; }

tr.r-row td { border-bottom: 1px solid var(--grid); }
tr.r-shared td { background: var(--mark-orange-bg); }
tr.r-claim td { background: var(--mark-yellow-bg); }
tr.r-challenged td { border-top: 2px solid var(--critical); border-bottom: 2px solid var(--critical); }
tr.r-challenged td:first-child { border-left: 2px solid var(--critical); border-radius: 6px 0 0 6px; }
tr.r-challenged td:last-child { border-right: 2px solid var(--critical); border-radius: 0 6px 6px 0; }
/* A settled item needs no outline of its own: it is already struck through and faded back, and a
   purple box around every closed row turned a settled column into noise. */
tr.r-linksrc td { outline: 2px dashed var(--series-1); }

.rbtn { border: 1px solid var(--border); background: var(--page); color: var(--text-secondary);
  border-radius: 7px; padding: 3px 8px; font-size: 11px; cursor: pointer; margin: 1px 2px 1px 0; white-space: nowrap; }
.rbtn.on-shared { background: #eb6834; border-color: #eb6834; color: #fff; }
.rbtn.on-challenge { background: var(--critical); border-color: var(--critical); color: #fff; }
.rbtn.on-paidback { background: var(--mark-purple); border-color: var(--mark-purple); color: #fff; }
.rbtn.on-link { background: var(--series-1); border-color: var(--series-1); color: #fff; }
.linkchip { display: inline-block; border: 1px solid var(--series-1); color: var(--series-1);
  border-radius: 999px; font-size: 10px; padding: 0 6px; margin-left: 3px; cursor: pointer; }

#tallybar { position: sticky; bottom: 0; z-index: 7; display: flex; flex-wrap: wrap;
  align-items: stretch; gap: 10px 18px;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: 12px 12px 0 0;
  padding: 10px 14px; margin-top: 18px; box-shadow: 0 -6px 18px rgba(0,0,0,.15); }
/* one group per column, plus the net. Each grows to share the width, and the whole bar wraps
   rather than shrinking the figures past readability. */
.tgroup { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.tgroup + .tgroup { border-left: 1px solid var(--border); padding-left: 18px; }
.tgcap { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-secondary); display: flex; gap: 8px; align-items: baseline; }
.tgcap .tgsub { text-transform: none; letter-spacing: 0; color: var(--muted); font-size: 10.5px; }
.tgrow { display: flex; flex-wrap: wrap; gap: 4px 16px; align-items: baseline; }
.tgrow .tally { min-width: 92px; }
.tally { display: flex; flex-direction: column; }
.tally .tl { font-size: 11px; color: var(--text-secondary); }
.tally .tv { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
.tgrow .tally .tv { font-size: 16px; }
.tgroup-net .tgrow .tally .tv { font-size: 20px; }
.tgrow .tally .tv.ms-paid { color: var(--good); }
#t-owe-her[title], #t-net[title] { cursor: help; text-decoration: underline dotted; text-underline-offset: 3px; }
.tally .th { font-size: 11px; color: var(--muted); }

#modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#challenge-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(520px, 94vw); box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#challenge-modal h3 { margin: 0 0 6px; }
#challenge-modal label { display: block; margin: 12px 0 4px; font-size: 13px; color: var(--text-secondary); }
#cm-reason { width: 100%; background: var(--page); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px; font: inherit; resize: vertical; }
.cm-actions { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.cm-actions button { border-radius: 8px; padding: 8px 14px; font: inherit; cursor: pointer;
  border: 1px solid var(--border); background: var(--page); color: var(--text-primary); }
.cm-actions .btn-primary { background: var(--series-1); border-color: var(--series-1); color: #fff; }
.cm-actions .btn-danger { background: var(--critical); border-color: var(--critical); color: #fff; }

@media (max-width: 900px) {
  .recon-pair, .recon-headrow { grid-template-columns: 1fr; gap: 10px; }
  #recon-svg { display: none; }
  .recon-headrow { position: static; }
  .recon-headcol { text-align: left; }
  .rbtn { padding: 7px 12px; font-size: 12px; }
}

#modal-backdrop[hidden] { display: none !important; }
.recon-pane td.chipcell { white-space: nowrap; }
.recon-pane td.chipcell .rbtn { display: inline-block; }

.recon-pane td { padding: 3px 5px; }
.rbtn { padding: 2px 6px; font-size: 10.5px; }
@media (max-width: 900px) { .rbtn { padding: 7px 12px; font-size: 12px; } }

/* small screens keep the REAL table layout: columns stack, and each pane
   (Ethan / Stephanie) scrolls horizontally on its own instead of squishing */
.pane-cap { display: none; }
@media (max-width: 900px) {
  .pane-cap { display: block; font-weight: 700; font-size: 13px; margin: 2px 0 6px; color: var(--text-secondary); }
  .recon-pane td.prime { max-width: 300px; }
  #tallybar { flex-direction: column; }
  .tgroup + .tgroup { border-left: 0; padding-left: 0;
    border-top: 1px solid var(--border); padding-top: 8px; }
}


/* wide recon layout + one-line rows */
body.wide main { max-width: 2400px; }
.recon-pane { padding: 8px 14px 8px 10px; }
.recon-pane table { table-layout: fixed; }
.recon-pane td, .recon-pane th { white-space: nowrap; }
/* width now comes from the fixed layout above, not a viewport cap */
.recon-pane td.chipcell { padding-right: 10px; }
.recon-pane tr.r-row td { line-height: 1.9; }
#earmark-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#earmark-backdrop[hidden] { display: none !important; }
#earmark-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(520px, 94vw); box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#earmark-modal h3 { margin: 0 0 6px; }
#earmark-modal label { display: block; margin: 12px 0 4px; font-size: 13px; color: var(--text-secondary); }
#em-note { width: 100%; background: var(--page); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px; font: inherit; resize: vertical; }
.earnote { color: #12905f; font-weight: 600; font-style: italic; }
:root[data-theme="dark"] .earnote { color: #2fc98a; }
@media (prefers-color-scheme: dark) { :root:where(:not([data-theme="light"])) .earnote { color: #2fc98a; } }
.earnote::before { content: "\1F3F7\FE0F  "; font-style: normal; }
.origdesc { color: var(--muted); font-size: 11px; font-weight: 400; }
.recon-controls select { background: var(--page); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 4px 6px; font: inherit; }

/* left-side controls in Ethan's rows: shared | note | cost precede the description */
td.chipcell.leftchips { white-space: nowrap; width: 1%; padding-right: 2px; }

/* ---------- amount override (adjust what the split is computed on) ---------- */
.ovorig { text-decoration: line-through; color: var(--muted); font-weight: 400; font-size: 10.5px; margin-left: 3px; }
.rbtn.on-adjust { background: #b45309; border-color: #b45309; color: #fff; }
/* split modal: divide one payment across its linked claims */
#split-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#split-backdrop[hidden] { display: none !important; }
#split-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(760px, 96vw); max-height: 90vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#split-modal h3 { margin: 0 0 6px; }
#sp-table { width: 100%; border-collapse: collapse; margin: 12px 0 6px; font-size: 12.5px; }
#sp-table th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); border-bottom: 1px solid var(--border); padding: 4px 6px; }
#sp-table td { padding: 6px; border-bottom: 1px solid var(--grid); vertical-align: top; }
#sp-table td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
#sp-table tr.sp-excluded td { color: var(--muted); }
.sp-amt { width: 110px; background: var(--page); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 6px; padding: 4px 6px; font: inherit; font-size: 12px; text-align: right; }
.sp-modes { margin: 8px 0 4px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 12px; color: var(--text-secondary); }
.sp-total { font-size: 12.5px; color: var(--text-secondary); padding: 4px 6px; }
.sp-left { color: #b45309; font-weight: 600; }
.sp-over { color: var(--link-line, #2a78d6); font-weight: 600; }
.sp-ok { color: var(--good); font-weight: 600; }
.sp-bad { color: var(--critical); font-weight: 600; }
.split-btn { border-color: var(--link-line) !important; color: var(--link-line) !important; }
/* a claim Ethan owes in full rather than as a share of a shared cost */
.rbtn.on-full { background: #b45309; border-color: #b45309; color: #fff; }
tr.r-full td:first-child { box-shadow: inset 3px 0 0 #b45309; }
tr.r-full td[data-l="value"] { font-weight: 700; }

/* a CLOSED item: settled, or linked to something settled. Neither party owes anything further,
   so it recedes and lets the open items carry the eye. The description is struck through; the
   amount is only dimmed, because a struck-through figure is genuinely hard to read back. */
/* A settled row drops its shared/claim tint and sits on the plain column background: the colour
   marks an item still in play, and keeping it made a closed column look busier than an open one.
   What is left is the fade and the strikethrough. */
tr.r-closed td { opacity: .55; background: var(--surface-1); transition: opacity .12s ease; }
tr.r-closed:hover td { opacity: .92; }          /* lean in and it comes back, for reading detail */
tr.r-closed td.prime { text-decoration: line-through; text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 55%, transparent); }
tr.r-closed td.prime .hint, tr.r-closed td.prime .remainchip,
tr.r-closed td.prime .linkchip,
tr.r-closed td.prime .entchip { text-decoration: none; }
tr.r-closed td[data-l="value"] { text-decoration: none; }
/* Stephanie's challenge on one of Ethan's shared expenses */
tr.r-row.r-challenged td:first-child { box-shadow: inset 3px 0 0 var(--critical); }
.chal-btn.on-challenge { background: var(--critical); border-color: var(--critical); color: #fff; }
body.locked button.rbtn.chal-btn { display: inline-block !important; }
.rbtn[disabled] { opacity: .4; cursor: not-allowed; }

/* shared expenses entered in the app */
body.locked button.rbtn.ent-btn { display: inline-block !important; }
.addexp { padding: 6px 2px 2px; }
.entchip { display: inline-block; margin-left: 7px; padding: 0 7px; border-radius: 999px;
  font-size: 10px; font-weight: 700; letter-spacing: .02em; cursor: help;
  background: color-mix(in srgb, var(--good) 16%, var(--surface-1));
  color: var(--good); border: 1px solid var(--good); }
.entchip.ent-pending { background: color-mix(in srgb, #b45309 16%, var(--surface-1));
  color: #b45309; border-color: #b45309; }
/* a proposal is visibly provisional until accepted */
tr.r-pending td { opacity: .72; border-top: 1px dashed #b45309; border-bottom: 1px dashed #b45309; }
tr.r-pending td:first-child { box-shadow: inset 3px 0 0 #b45309; }
@keyframes rflash { 0%,100% { background: transparent; } 35% { background: color-mix(in srgb, #eda100 40%, transparent); } }
tr.r-flash td { animation: rflash 1.6s ease; }
#pendingbtn { border: 1px solid #b45309; background: #b45309; color: #fff; border-radius: 999px;
  padding: 4px 12px; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600; }
#importbtn { border: 1px solid var(--border); background: var(--page); color: var(--text-secondary);
  border-radius: 999px; padding: 4px 12px; cursor: pointer; font: inherit; font-size: 12px; }
#pendingbtn[hidden], #importbtn[hidden] { display: none !important; }
.btn-primary-lite { color: var(--good); border-color: var(--good) !important; }

#exp-backdrop, #imp-backdrop, #pf-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5);
  z-index: 30; display: flex; align-items: center; justify-content: center; padding: 16px; }
#exp-backdrop[hidden], #imp-backdrop[hidden], #pf-backdrop[hidden] { display: none !important; }
/* the proof reader: big enough to actually read an invoice in, and it closes only by its buttons */
#pf-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(1000px, 96vw); max-height: 94vh;
  display: flex; flex-direction: column; box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#pf-modal h3 { margin: 0 0 4px; }
#pf-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; }
#pf-tabs:empty { display: none; }
#pf-view { flex: 1; min-height: 0; margin-top: 10px; border: 1px solid var(--border);
  border-radius: 10px; overflow: auto; background: var(--page);
  display: flex; align-items: center; justify-content: center; }
/* a PDF needs room; an image should fit rather than force a scroll to see all of it */
#pf-view iframe { width: 100%; height: 72vh; border: 0; background: #fff; }
#pf-view img { max-width: 100%; max-height: 72vh; object-fit: contain; display: block; }
#pf-download { text-decoration: none; display: inline-block; }
/* the list of what is already attached, inside the entry modal */
#ex-proof-list:empty { display: none; }
#ex-proof { width: 100%; }
#exp-modal, #imp-modal { background: var(--surface-1); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 14px; padding: 18px; max-height: 92vh;
  overflow-y: auto; box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#exp-modal { width: min(520px, 94vw); } #imp-modal { width: min(760px, 96vw); }
#exp-modal h3, #imp-modal h3 { margin: 0 0 6px; }
#exp-modal label, #imp-modal label { display: block; margin: 12px 0 4px; font-size: 13px; color: var(--text-secondary); }
#exp-modal input[type=date], #exp-modal input[type=number], #exp-modal input[type=text],
#exp-modal #ex-desc, #exp-modal textarea, #imp-modal textarea {
  width: 100%; background: var(--page); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px; font: inherit; }
#exp-modal textarea, #imp-modal textarea { resize: vertical; }
.ex-acctrow { display: flex; gap: 8px; align-items: center; }
.ex-acctrow select { flex: 1; background: var(--page); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 8px; padding: 8px; font: inherit; }
label.ex-check { display: flex !important; align-items: flex-start; gap: 8px; margin-top: 14px; }
label.ex-check input { margin-top: 3px; }
#im-file { margin-top: 8px; font-size: 12px; }
#im-preview { margin-top: 12px; }
.imp-bad { color: var(--critical); font-size: 12px; margin-bottom: 6px; }
.imp-ok { color: var(--good); font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.imp-tbl { width: 100%; border-collapse: collapse; font-size: 12px; }
.imp-tbl th { text-align: left; font-size: 10px; text-transform: uppercase; color: var(--muted);
  border-bottom: 1px solid var(--border); padding: 3px 6px; }
.imp-tbl td { padding: 3px 6px; border-bottom: 1px solid var(--grid); }
.imp-tbl td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* rows Ethan added because Stephanie never produced a record for them */
tr.r-custom td { background: color-mix(in srgb, var(--rec-line) 10%, var(--surface-1)); }
tr.r-custom td:first-child { box-shadow: inset 3px 0 0 var(--rec-line); }
.custchip { display: inline-block; margin-left: 7px; padding: 0 6px; border-radius: 999px;
  font-size: 10px; color: var(--rec-line); border: 1px dashed var(--rec-line); cursor: help; }
.addrec { padding: 6px 2px 2px; }
.btn-danger-lite { color: var(--critical); }
/* evidence match to a row in her own records: teal, never blue, because it changes no total */
.reclinkchip { border-color: var(--rec-line) !important; color: var(--rec-line) !important; }

#custrec-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#custrec-backdrop[hidden] { display: none !important; }
#custrec-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(520px, 94vw); max-height: 92vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#custrec-modal h3 { margin: 0 0 6px; }
#custrec-modal label { display: block; margin: 12px 0 4px; font-size: 13px; color: var(--text-secondary); }
#custrec-modal input, #custrec-modal textarea { width: 100%; background: var(--page);
  color: var(--text-primary); border: 1px solid var(--border); border-radius: 8px; padding: 8px; font: inherit; }
#custrec-modal textarea { resize: vertical; }

/* xlsx source viewer */
#sheet-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#sheet-backdrop[hidden] { display: none !important; }
#sheet-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 14px 16px; width: min(1100px, 96vw); max-height: 90vh;
  display: flex; flex-direction: column; box-shadow: 0 12px 40px rgba(0,0,0,.4); }
.sh-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 10px;
  cursor: move; touch-action: none; user-select: none; }
.sh-head select, .sh-head button, .sh-head a { cursor: pointer; }
#sheet-modal.sh-dragging { box-shadow: 0 18px 50px rgba(0,0,0,.5); }
#sheet-modal.sh-dragging #sh-body { pointer-events: none; }
.sh-head h3 { margin: 0; font-size: 14px; }
.sh-head select { font: inherit; font-size: 12px; padding: 2px 4px; border: 1px solid var(--border);
  border-radius: 6px; background: var(--page); color: var(--text-primary); }
.sh-spacer { flex: 1; }
#sh-body { overflow: auto; border: 1px solid var(--border); border-radius: 8px; }
#sh-table { border-collapse: collapse; width: 100%; font-size: 12px; }
#sh-table th, #sh-table td { border: 1px solid var(--grid); padding: 3px 7px; text-align: left;
  white-space: nowrap; vertical-align: top; }
#sh-table thead th { position: sticky; top: 0; background: var(--surface-1); z-index: 1;
  color: var(--muted); font-size: 10px; font-weight: 600; }
#sh-table .sh-gut { background: var(--page); color: var(--muted); font-variant-numeric: tabular-nums;
  text-align: right; font-size: 10.5px; position: sticky; left: 0; }
/* the row this claim was pulled from */
#sh-table tr.sh-hit td { background: var(--mark-yellow-bg); font-weight: 600;
  border-top: 2px solid #eda100; border-bottom: 2px solid #eda100; }
#sh-table tr.sh-hit td.sh-gut { background: #eda100; color: #1a1a19; }

#unlock-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#unlock-backdrop[hidden] { display: none !important; }
#unlock-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(430px, 94vw); box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#unlock-modal h3 { margin: 0 0 6px; }
#unlock-modal label { display: block; margin: 12px 0 4px; font-size: 13px; color: var(--text-secondary); }
#ul-pw { width: 100%; background: var(--page); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px; font: inherit; letter-spacing: 2px; }
.ul-err { margin-top: 8px; font-size: 12px; color: var(--critical); }
.ul-err[hidden] { display: none !important; }

#override-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#override-backdrop[hidden] { display: none !important; }
#override-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(520px, 94vw); box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#override-modal h3 { margin: 0 0 6px; }
#override-modal label { display: block; margin: 12px 0 4px; font-size: 13px; color: var(--text-secondary); }
#ov-amount, #ov-note { width: 100%; background: var(--page); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 8px; padding: 8px; font: inherit; }
#ov-note { resize: vertical; }
@media (max-width: 900px) {
  .recon-pane td, .recon-pane th { white-space: normal; }
  .recon-pane td.prime { max-width: none; }
  .recon-pane tr.r-row td { line-height: 1.45; }
}


.provchip { display: inline-block; margin-left: 6px; padding: 0 7px; border-radius: 999px;
  font-size: 10px; font-weight: 600; vertical-align: 1px; cursor: help; }
.prov-no_statement { background: color-mix(in srgb, var(--muted) 22%, transparent); color: var(--text-secondary);
  border: 1px dashed var(--muted); }
.prov-in_statements { background: color-mix(in srgb, #0ca30c 15%, transparent); color: var(--good);
  border: 1px solid var(--good); }
.prov-not_found { background: color-mix(in srgb, var(--critical) 14%, transparent); color: var(--critical);
  border: 1px solid var(--critical); }


tr.r-record td { background: none; }
/* per-month subtotal, sitting between her claims and her account records */
.monthsum { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 18px; margin-top: 8px;
  padding: 7px 10px; border: 1px solid var(--border); border-left: 3px solid var(--mark-yellow-bg);
  border-radius: 8px; background: var(--page); cursor: help; }
.ms-item { display: inline-flex; align-items: baseline; gap: 6px; }
.ms-l { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 600; }
.ms-v { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.ms-v.ms-paid { color: var(--good); }
.ms-net .ms-v { color: #b45309; }
.ms-item[data-hl] { cursor: help; padding: 2px 6px; border-radius: 6px; transition: background .12s ease; }
.ms-item[data-hl]:hover { background: color-mix(in srgb, #eda100 20%, var(--surface-1)); }

/* hovering a footer figure: light up the rows it is made of, fade the rest, and badge each row
   with what it contributes. The point is to SHOW the arithmetic, not just assert it. */
.hl-active tr[data-kind="claim"] { opacity: .28; transition: opacity .12s ease; }
.hl-active tr[data-kind="claim"].hl-on { opacity: 1; }
/* his footer explains his own column, so it fades his rows instead of her claims */
.hl-active-e tr[data-kind="txn"]:not([data-rec]) { opacity: .28; transition: opacity .12s ease; }
.hl-active-e tr[data-kind="txn"].hl-on { opacity: 1; }
.hl-active tr.hl-on td, .hl-active-e tr.hl-on td { background: color-mix(in srgb, #eda100 22%, var(--surface-1)); }
.hl-active tr.hl-on td:first-child, .hl-active-e tr.hl-on td:first-child { box-shadow: inset 3px 0 0 #eda100; }
/* Ethan's footer mirrors hers but takes his column's orange accent */
.monthsum.ms-ethan { border-left-color: var(--mark-orange-bg); }
.hlbadge { display: inline-block; margin-left: 8px; padding: 0 7px; border-radius: 999px;
  background: #b45309; color: #fff; font-size: 10.5px; font-weight: 700; white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.ms-note { margin-left: auto; font-size: 11px; color: var(--muted); }

.recdetails { margin-top: 8px; border-top: 1px dashed var(--baseline); padding-top: 6px; }
.recdetails summary { cursor: pointer; font-size: 12px; font-weight: 600; color: var(--text-secondary);
  padding: 4px 0; list-style-position: inside; }
.recdetails summary:hover { color: var(--text-primary); }
.norecords { margin-top: 8px; padding: 8px 10px; border: 1px dashed var(--critical); border-radius: 8px;
  color: var(--critical); font-size: 12px; }
.rbtn.cand { border-style: dashed; border-color: var(--series-1); color: var(--series-1); }


.prov-near_match { background: color-mix(in srgb, #eda100 16%, transparent); color: #c98500;
  border: 1px solid #c98500; }


/* floating account key: container is JUST the button; the body overlays, anchored to it */
#acct-key { position: fixed; right: 14px; bottom: 110px; z-index: 25; width: 40px; height: 40px; }
#acct-key-toggle { width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--border);
  background: var(--surface-1); font-size: 17px; cursor: pointer;
  box-shadow: 0 4px 14px rgba(0,0,0,.25); }
#acct-key-body { position: absolute; background: var(--surface-1); border: 1px solid var(--border);
  border-radius: 12px; padding: 10px 12px; width: min(340px, 92vw); font-size: 11.5px;
  box-shadow: 0 8px 24px rgba(0,0,0,.3); max-height: 74vh; overflow-y: auto; }
#acct-key-body.ak-down { top: 48px; } #acct-key-body.ak-up { bottom: 48px; }
#acct-key-body.ak-right-align { right: 0; } #acct-key-body.ak-left-align { left: 0; }
#acct-key.collapsed #acct-key-body { display: none; }
.ak-title { font-weight: 700; font-size: 12px; margin-bottom: 4px; }
.ak-group { color: var(--muted); font-weight: 600; font-size: 10px; text-transform: uppercase;
  letter-spacing: .04em; margin: 7px 0 2px; }
.ak-row { display: flex; justify-content: space-between; gap: 8px; padding: 1px 0;
  color: var(--text-secondary); }
.ak-row b { color: var(--text-primary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ak-hint { color: var(--muted); font-size: 10px; font-style: italic; margin-top: 1px; }
@media (max-width: 900px) {
  #acct-key { bottom: 160px; right: 8px; }
  #acct-key-body { width: min(300px, 88vw); }
}


#acct-key { cursor: grab; touch-action: none; user-select: none; }
#acct-key.dragging { cursor: grabbing; }
#acct-key.dragging #acct-key-body, #acct-key.dragging #acct-key-toggle { pointer-events: none; }


/* the month bar pins under the column headrow and rides down with the page; still click-to-fold.
   --month-top is measured in JS because the headrow's height changes between view-only and management. */
details.recon-month > summary { cursor: pointer; list-style: none; display: flex; align-items: baseline;
  gap: 14px; flex-wrap: wrap; border-bottom: 1px solid var(--baseline); margin: 0 0 6px;
  /* z-index 0 in flow so connector lines (1) cross it like they cross rows; 2 once pinned, when it
     becomes chrome floating over the grid and lines must tuck behind. is-stuck is set in JS. */
  position: sticky; top: var(--month-top, 120px); z-index: 0; background: var(--page);
  padding: 6px 4px 4px; }
details.recon-month > summary.is-stuck { z-index: 2; }
details.recon-month > summary::before { content: "▸"; color: var(--muted); font-size: 12px; }
details.recon-month[open] > summary::before { content: "▾"; }
details.recon-month > summary h3 { margin: 0; border: none; padding: 0; display: inline; }
/* ⛓ N pill on a collapsed month bar: linked rows live inside it */
summary .linkbadge { font-size: 11px; font-weight: 600; color: var(--link-line, #2a78d6);
  border: 1px dashed var(--link-line, #2a78d6); border-radius: 999px; padding: 1px 8px;
  white-space: nowrap; cursor: help; }
.eomstrip { display: inline-flex; gap: 12px; flex-wrap: wrap; font-size: 11px; color: var(--muted); }
.eomitem b { color: var(--text-secondary); font-weight: 600; font-variant-numeric: tabular-nums; }


.eomlabel { color: var(--muted); font-weight: 600; font-size: 10px; text-transform: uppercase; }

/* drag-to-link grips */
.lgrip { cursor: grab; user-select: none; touch-action: none; color: var(--muted);
  padding: 0 5px; font-size: 11px; display: inline-block; }
.lgrip:hover { color: var(--series-1); }
/* the grip doubles as the only permanent marker that a row is linked */
.lgrip.has-links { color: var(--series-1); opacity: 1; font-weight: 700; }
/* his grip sits at the right edge of his row and hers at the left of hers, so the two handles
   face each other across the gap they are dragged over */
td.gripcell { text-align: right; padding-right: 4px; width: 1%; white-space: nowrap; }
/* value, account/source and date read as centred columns in BOTH panes; only the description,
   which is prose of wildly varying length, stays ranged left. Headings follow their cells. */
.recon-pane td[data-l="value"], .recon-pane th:nth-child(2),
.recon-pane td[data-l="src"],   .recon-pane th:nth-child(3),
.recon-pane td[data-l="date"],  .recon-pane th:nth-child(4) { text-align: center; }
.recon-pane td[data-l="value"] { font-variant-numeric: tabular-nums; }
.recon-pane td.prime, .recon-pane th:first-child { text-align: left; }
/* The three data columns are a fixed block hard against the right edge, 10px apart, and the
   description takes whatever is left and truncates. Fixed layout, because with auto layout a long
   description sets the table's minimum width and pushes the block off the edge of the pane. */
.recon-pane table { table-layout: fixed; width: 100%; }
.recon-pane th:nth-child(1), .recon-pane td.prime { width: auto; max-width: none;
  overflow: hidden; text-overflow: ellipsis; padding-right: 10px; }
.recon-pane th:nth-child(2), .recon-pane td[data-l="value"] { width: 96px; }
.recon-pane th:nth-child(3), .recon-pane td[data-l="src"]   { width: 150px; }
.recon-pane th:nth-child(4), .recon-pane td[data-l="date"]  { width: 62px; }
.recon-pane th:nth-child(5), .recon-pane td.chipcell        { width: 26px; }
.recon-pane td[data-l], .recon-pane th:nth-child(2),
.recon-pane th:nth-child(3), .recon-pane th:nth-child(4) {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  padding-left: 10px; padding-right: 0; }
.lgrip:not(.has-links) { opacity: .3; }
.lgrip:not(.has-links):hover { opacity: 1; }
body.linkdragging, body.linkdragging * { cursor: grabbing !important; }
#recon-svg #rubber { pointer-events: none; }

/* Connector lines are SILENT by default: a screen full of them is unreadable. Hovering a row (or
   its chip) reveals that row's lines; clicking the row pins them on. Revealed lines run as dashes
   marching the way the money moved, so the picture reads as flow rather than as static wiring. */
@keyframes linkflow { to { stroke-dashoffset: -32px; } }
#recon-svg [data-link], #recon-svg [data-reclink], #recon-svg [data-slink], #recon-svg [data-blink] {
  opacity: 0; transition: opacity .16s ease; pointer-events: none; }
#recon-svg path.flow-on { opacity: 1; stroke-width: 3.5; stroke-dasharray: 10 6;
  stroke-linecap: butt; animation: linkflow .5s linear infinite; pointer-events: stroke; }
#recon-svg path.flow-on.dimmed { opacity: .6; }
#recon-svg path.flow-on[data-dir="in"] { animation-direction: reverse; }
#recon-svg circle.flow-on { opacity: 1; }
#recon-svg circle.flow-on.dimmed { opacity: .6; }
/* the settlement chain is its own colour: it is an outcome, not a payment link */
#recon-svg path.settleline.flow-on { stroke-dasharray: 9 7; }
.linkchip { transition: transform .12s ease; }
.linkchip:hover { transform: scale(1.25); }
/* one-to-many: a single payment spread over many claims */
.manychip { border-color: var(--many-line) !important; color: var(--many-line) !important;
  background: color-mix(in srgb, var(--many-line) 14%, transparent); font-weight: 700; }
/* the same chip when the spread came from a reimbursement, matching its pink lines */
.paychip { border-color: var(--pay-line) !important; color: var(--pay-line) !important;
  background: color-mix(in srgb, var(--pay-line) 14%, transparent); }
/* the offset half of a settle-up: his own items, matching the settlement lines */
.offsetchip { border-color: var(--settle-line) !important; color: var(--settle-line) !important;
  background: color-mix(in srgb, var(--settle-line) 14%, transparent); font-weight: 700; }
/* flow toggles: hold a whole kind of line on, for reading the page rather than one row */
#flowbar { align-items: center; gap: 4px 14px; }
#flowbar .fl-cap { font-size: 12px; color: var(--text-secondary); font-weight: 600; }
.fl-item { display: inline-flex; align-items: center; gap: 5px; font-size: 12px;
  color: var(--text-secondary); cursor: pointer; white-space: nowrap; }
.fl-item .fl-swatch { width: 22px; height: 0; border-top: 3px dashed currentColor; border-radius: 2px; }
.fl-payment { color: var(--link-line); }
.fl-reimbursement { color: var(--pay-line); }
.fl-offset { color: var(--settle-line); }
.fl-record { color: var(--rec-line); }
.fl-reimbursement { color: var(--settle-line); }
.fl-overpaid { color: #b45309; }
/* an overpaid item, held lit by the toggle. Warm rather than alarming: money coming BACK is not a
   problem, it just has to be visible to be believed. */
tr.r-overlit > td { background: color-mix(in srgb, #b45309 16%, transparent) !important;
  box-shadow: inset 2px 0 0 #b45309; }
.overbadge { display: inline-block; margin-left: 8px; padding: 0 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; white-space: nowrap; vertical-align: middle;
  color: #fff; background: #b45309;
  /* these rows are settled, so the row text is struck through; the badge must not be */
  text-decoration: none; }
tr.r-overlit .overbadge { text-decoration: none !important; }
/* Rows held lit by the reimbursement toggle. Quieter than the neon r-lit that a CLICK produces:
   this can be on across the whole page, and at that volume the full glow is a wall of light. */
tr.r-flowlit > td { background: color-mix(in srgb, var(--settle-line) 13%, transparent) !important;
  box-shadow: inset 2px 0 0 var(--settle-line); }
tr.r-flowlit.r-lit > td { box-shadow: none; }   /* a clicked relationship still wins */
#fl-none[hidden] { display: none; }

/* a row whose lines are pinned on */
tr.r-pinned > td { background: color-mix(in srgb, var(--series-1) 12%, transparent) !important; }
tr.r-pinned > td:first-child { box-shadow: inset 3px 0 0 var(--series-1); }
#recon-grid tr[data-id] { cursor: pointer; }
#pinclear { margin-left: 8px; }
/* the NET settlement placeholder in her column */
/* separate, not collapse: collapsed borders disable border-radius on cells and swallow the
   neon glow's box-shadow. It is a single-cell table, so nothing else cares. */
.settletbl { width: 100%; border-collapse: separate; border-spacing: 0; margin-top: 6px; }
tr.r-settlement > td { background: color-mix(in srgb, var(--settle-line) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--settle-line) 45%, transparent); padding: 7px 9px;
  border-radius: 10px; }
tr.r-settlement .setmark { display: inline-block; margin-right: 7px; padding: 1px 7px;
  border-radius: 9px; font-size: 11px; font-weight: 700; color: #fff;
  background: var(--settle-line); }
tr.r-settlement .hint { margin-top: 3px; }
tr.r-settlement .setexcess { color: #b45309; font-weight: 600; }
tr.r-settlement.r-pinned > td { background: color-mix(in srgb, var(--settle-line) 22%, transparent) !important; }
.undo-btn { border-color: #c2410c !important; color: #c2410c !important; }
@media (prefers-reduced-motion: reduce) {
  #recon-svg path.flow-on { animation: none; }
  .linkchip, #recon-svg [data-link], #recon-svg [data-reclink], #recon-svg [data-slink], #recon-svg [data-blink] { transition: none; }
}
tr.r-droptarget td { outline: 2px dashed var(--series-1); outline-offset: -2px; }

/* alignment panel */
#align-panel summary { cursor: pointer; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
#align-panel summary h2 { display: inline; margin: 0; font-size: 15px; }
#align-summary { margin: 8px 0; max-width: 1100px; }
#align-table { width: 100%; border-collapse: collapse; }
#align-table th { text-align: left; font-size: 11px; color: var(--text-secondary); padding: 4px 8px; }
#align-table td { padding: 4px 8px; border-top: 1px solid var(--border); font-size: 12.5px; vertical-align: top; }
#align-table td[data-l="yours"], #align-table td[data-l="hers"] { font-variant-numeric: tabular-nums; }
#align-table td .hint { font-size: 11px; }
tr.al-both td { background: var(--mark-yellow-bg); }
.alchip { display: inline-block; padding: 0 8px; border-radius: 999px; font-size: 11px; white-space: nowrap; }
.al-both { border: 1px solid #eda100; background: var(--mark-yellow-bg); }
.al-e { border: 1px solid #eb6834; background: var(--mark-orange-bg); }
.al-s { border: 1px solid var(--series-1); color: var(--series-1); }
#align-credits { margin-top: 10px; max-width: 1100px; }

/* transfer counterparty chips */
.xferchip { display: inline-block; margin-left: 6px; padding: 0 7px; border-radius: 999px;
  font-size: 10.5px; border: 1px solid var(--border); color: var(--text-secondary); white-space: nowrap; }
.xf-confirmed { border-color: var(--series-1); color: var(--series-1); }
.xf-matched { border-color: var(--series-1); color: var(--series-1); border-style: dashed; }
.xf-wording { border-style: dashed; }
.xf-ambiguous { border-color: #eda100; color: #a97a00; }
.xf-unmatched { border-style: dotted; color: var(--muted); }

/* color tags */
.rbtn.cdot { min-width: 22px; }
#color-pop { position: fixed; z-index: 400; display: flex; gap: 6px; padding: 8px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface-1);
  box-shadow: 0 6px 24px rgba(0,0,0,.18); }
/* the display:flex above beats the hidden attribute's UA default, so hide explicitly */
#color-pop[hidden] { display: none !important; }
/* color-tagged rows: tint every cell, full-strength stripe on the row's first cell */
tr.r-colored td { background: color-mix(in srgb, var(--rowc) 22%, var(--surface-1)); }
tr.r-colored td:first-child { box-shadow: inset 5px 0 0 var(--rowc); }
.cp-swatch { width: 24px; height: 24px; border-radius: 7px; border: 1px solid var(--border); cursor: pointer; padding: 0; }
.cp-none { background: transparent; color: var(--muted); font-size: 13px; }
.cl-item { display: flex; align-items: baseline; gap: 6px;
  font-size: 11px; color: var(--text-secondary); }
.cl-item .cl-name { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.cl-item .cl-unnamed { color: var(--muted); font-style: italic; }
.cl-swatch { width: 14px; height: 14px; flex: 0 0 14px; border-radius: 4px;
  border: 1px solid var(--border); cursor: pointer; padding: 0; align-self: center; }
/* view-only: the swatch is a legend key, not a control */
.cl-swatch[disabled] { cursor: default; }

/* note (earmark) button active state matches the green note text it produces */
.rbtn.on-note { background: #12905f; border-color: #12905f; color: #fff; }
:root[data-theme="dark"] .rbtn.on-note { background: #1d7a55; border-color: #1d7a55; }

/* grip is now the ONLY linking affordance: make it visible */
.lgrip { color: var(--series-1); opacity: .5; font-size: 12px; }
.lgrip:hover { opacity: 1; }

/* per-column filters in the sticky header row */
.colfilter { display: flex; gap: 6px; margin-top: 6px; align-items: center; font-weight: 400; }
.colfilter input { flex: 1; min-width: 0; padding: 3px 8px; font-size: 12px;
  border: 1px solid var(--border); border-radius: 7px; background: var(--page); color: inherit; }
.colfilter select { font-size: 12px; padding: 2px 4px; border: 1px solid var(--border);
  border-radius: 7px; background: var(--page); color: inherit; }
.colfilter .fcount { font-size: 11px; color: var(--muted); white-space: nowrap; }

/* alignment table: center the two amount columns (header + cells) */
#align-table th:nth-child(3), #align-table th:nth-child(4),
#align-table td[data-l="yours"], #align-table td[data-l="hers"] { text-align: center; }

/* net-settlement tile: the number that matters most */
.tally-net { padding-left: 14px; border-left: 3px solid var(--series-1); }
.tally-net .tv { font-size: 24px; color: var(--series-1); }

/* credit rows: her own doc acknowledging Ethan's payments */
tr.r-credit td { background: color-mix(in srgb, #2f9e44 12%, var(--surface-1)); }
tr.r-credit td.prime { color: #12905f; font-weight: 600; }
:root[data-theme="dark"] tr.r-credit td.prime { color: #2fc98a; }
.lg-green::before { background: color-mix(in srgb, #2f9e44 12%, var(--surface-1)); border: 1px solid #2f9e44; }

/* made-whole note on claim rows + informational acknowledgment rows */
.setnote { color: var(--muted); }   /* reads as supporting detail, not as a mark */
/* What an item still owed when a settlement closed it: the one number a settled row cannot
   otherwise show, since settled items drop out of the live balance math. Drawn as a filled pill
   rather than coloured text because the row is faded to 45% and a child cannot outrank its
   parent's opacity, so only a solid block still reads at a glance. */
/* partially-covered claim: what the linked payments left unpaid */
.remainchip { color: #b45309; font-weight: 600; cursor: help; }
.remainchip.rc-ok { color: var(--good); }
.remainchip.rc-over { color: var(--link-line, #2a78d6); }
tr.r-ack td { background: transparent; opacity: .75; }
tr.r-ack td.prime { font-weight: 400; }
/* the "Stephanie pays Ethan" direction tile, mirroring the NET tile */
.tally.tally-dir { border-left: 3px solid var(--chip-h); padding-left: 10px; }
.tally.tally-dir .tv { color: var(--chip-h); }
.lg-closed::before { background: transparent; border: 1px solid var(--baseline); opacity: .5; }
#syncbtn { border: 1px solid var(--series-1); background: var(--page); color: var(--series-1);
  border-radius: 999px; padding: 4px 12px; cursor: pointer; font: inherit; font-size: 12px; font-weight: 600; }
#syncbtn[disabled] { opacity: .6; cursor: progress; }
#syncbtn[hidden] { display: none !important; }
/* apply-one-payment-to-many modal */
#dist-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 30;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#dist-backdrop[hidden] { display: none !important; }
#dist-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(900px, 96vw); max-height: 92vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#dist-modal h3 { margin: 0 0 6px; }
.di-controls { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin: 12px 0 4px; }
.di-controls select { font: inherit; font-size: 12px; padding: 3px 6px; border: 1px solid var(--border);
  border-radius: 6px; background: var(--page); color: var(--text-primary); }
label.di-check { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-secondary); }
#di-list { max-height: 46vh; overflow-y: auto; margin-top: 8px; }
#di-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
#di-table th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); border-bottom: 1px solid var(--border); padding: 4px 6px;
  position: sticky; top: 0; background: var(--surface-1); }
#di-table td { padding: 5px 6px; border-bottom: 1px solid var(--grid); }
#di-table td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
#di-table tr.di-off td { opacity: .4; }
/* How the payment sits against the NET. Green when it is enough to square both columns, neutral
   when it is not: the arithmetic is shown either way, so the offset is never invisible. */
.di-net { margin: 10px 0 4px; padding: 10px 12px; border-radius: 8px; font-size: 12.5px; line-height: 1.5;
  background: color-mix(in srgb, var(--good) 12%, var(--surface-1)); border: 1px solid var(--good); }
/* the settle-up modal: which of his shared expenses are cancelled against the net.
   Closes only via its own buttons, never a backdrop click. */
/* the row panel: everything about one line item, since the row itself is a single line */
/* Above the month bars, which are inline content that happens to be sticky: a bar cutting a band
   out of the middle of an open panel reads as broken. Still BELOW the outer chrome — column
   headers (5), page header (6), tally footer (7) — so it slides under those on scroll as a row
   does. Ties with the connector lines at 4 and wins on DOM order, so it is never sliced by one. */
#rowpanel { position: fixed; z-index: 4; overscroll-behavior: contain; width: min(430px, 92vw); overflow-y: auto;
  background: var(--surface-1); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 12px; padding: 10px 12px;
  box-shadow: 0 10px 30px rgba(0,0,0,.35); pointer-events: none; font-size: 12.5px; }
#rowpanel[hidden] { display: none !important; }
#rowpanel.locked { pointer-events: auto; border-color: var(--series-1);
  box-shadow: 0 10px 34px rgba(0,0,0,.45), 0 0 0 2px color-mix(in srgb, var(--series-1) 35%, transparent); }
.rpx-head { border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
  padding-bottom: 6px; margin-bottom: 6px; }
.rpx-title { font-weight: 700; line-height: 1.35; }
.rpx-sub { color: var(--muted); font-size: 11.5px; margin-top: 2px; }
.rpx-links { margin-bottom: 6px; }
#ul2-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 33;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#ul2-backdrop[hidden] { display: none !important; }
#ul2-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(760px, 96vw); max-height: 92vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#ul2-list { max-height: 52vh; overflow-y: auto; margin-top: 6px; }
#ul2-go:disabled { opacity: .45; cursor: not-allowed; }
#ask-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 60;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#ask-backdrop[hidden] { display: none !important; }
#ask-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(460px, 94vw);
  box-shadow: 0 12px 40px rgba(0,0,0,.45); }
#ask-modal .hint { line-height: 1.5; }
.rpx-linkhead { font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); font-weight: 600; margin-bottom: 4px; }
.rpx-links { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent); padding-bottom: 8px; }
.rpx-notes { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.rp-note { color: var(--text-secondary); line-height: 1.45; }
.rp-note.rp-warn { color: var(--critical); }
.rpx-acts { display: flex; flex-direction: column; gap: 6px;
  border-top: 1px solid color-mix(in srgb, var(--border) 55%, transparent); padding-top: 8px; }
.rpx-act { display: grid; grid-template-columns: 104px 1fr; gap: 8px; align-items: start; }
.rpx-btn { display: flex; justify-content: flex-start; }
.rpx-btn .rbtn { margin: 0; }
.rpx-desc { color: var(--text-secondary); font-size: 11.5px; line-height: 1.4; }
/* ---------- the discussion on a line item ---------- */
.rpx-thread { margin-top: 9px; padding-top: 8px;
  border-top: 1px solid color-mix(in srgb, var(--border) 55%, transparent); }
.nt-cap { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--text-secondary); margin-bottom: 6px; }
.nt-empty, .nt-hint { color: var(--muted); font-size: 11.5px; font-style: italic; }
.nt-hint { margin-top: 6px; }
.nt-msg { margin-bottom: 7px; padding: 5px 8px; border-radius: 8px;
  background: color-mix(in srgb, var(--border) 22%, transparent); }
/* your own messages pick up the accent, so a thread is readable at a glance without reading names */
.nt-msg.nt-mine { background: color-mix(in srgb, var(--series-1) 13%, transparent);
  box-shadow: inset 2px 0 0 var(--series-1); }
.nt-head { display: flex; align-items: baseline; gap: 7px; margin-bottom: 2px; }
.nt-who { font-weight: 600; font-size: 11.5px; }
.nt-when { color: var(--muted); font-size: 10.5px; }
.nt-del { margin-left: auto !important; padding: 0 5px !important; font-size: 10px !important;
  line-height: 1.5 !important; color: var(--muted) !important; }
.nt-del:hover { color: var(--critical) !important; border-color: var(--critical) !important; }
.nt-body { font-size: 12px; line-height: 1.45; white-space: pre-wrap; word-break: break-word; }
.nt-new { display: flex; gap: 6px; align-items: flex-end; margin-top: 7px;
  position: sticky; bottom: -10px; background: var(--surface-1); padding: 6px 0 4px; }
.nt-input { flex: 1; min-width: 0; resize: vertical; font: inherit; font-size: 12px;
  padding: 5px 7px; border-radius: 7px; border: 1px solid var(--border);
  background: var(--page); color: var(--text); }
.nt-input:focus { outline: none; border-color: var(--series-1); }
.nt-post { flex: none; }
/* the count beside a row, so a discussion is visible without hovering every item */
/* a bank refresh that has started failing must be impossible to scroll past */
/* who the page thinks you are, next to the padlock. Quiet by default; the admin case is worth
   seeing at a glance, because it is the mode where a click changes real numbers. */
/* The preview bar. Deliberately loud and always on screen: forgetting you are inside a preview
   and wondering why nothing saves is the obvious way this feature goes wrong. */
#viewbar { position: sticky; top: 0; z-index: 8; display: flex; align-items: center; gap: 9px;
  padding: 7px 14px; font-size: 12.5px; color: #fff; background: #b45309;
  box-shadow: 0 2px 8px rgba(0,0,0,.3); }
#viewbar[hidden] { display: none !important; }
#viewbar .vb-dot { width: 8px; height: 8px; border-radius: 50%; background: #fff; flex: none; }
#viewbar .rbtn { margin-left: auto; color: #fff !important; border-color: #fff !important;
  background: transparent !important; }
/* the dismiss sits next to "leave the preview", not pushed to the far side */
#viewbar .vb-x { margin-left: 0; padding: 2px 8px !important; }
#viewas-wrap { display: inline-flex; align-items: center; gap: 6px; margin-right: 12px;
  font-size: 12px; color: var(--text-secondary); }
#viewas-wrap[hidden] { display: none !important; }
#viewas { background: var(--page); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 3px 7px; font: inherit; font-size: 12px; }
.authnote { font-size: 12px; color: var(--text-secondary); margin-right: 10px; }
.authnote:empty { display: none; }
.authnote.au-admin { color: var(--good); font-weight: 600; }
/* ---------- flatten for capture ----------
   A scrolling screenshot tool works by scrolling the window and stitching the frames together.
   Sticky chrome is painted in EVERY frame, so the header, the column titles and the totals bar
   come out repeated down the stitched image roughly once per screen.
   The cure is to stop them sticking, NOT to move the scrolling into an inner element: a tool that
   scrolls the window would then have nothing to scroll, and would capture one screen forever.
   The document stays the scroller; the chrome simply takes its place in the flow and appears once. */
body.flatten header,
body.flatten .recon-headrow,
body.flatten #tallybar,
body.flatten #viewbar,
body.flatten details.recon-month > summary { position: static !important; }
/* floating things have no place in the flow at all, so they would otherwise land once, at whatever
   point the page happened to be scrolled to */
body.flatten #acct-key,
body.flatten #rowpanel { display: none !important; }
/* Nothing may be mid-movement while frames are being captured. The marching dashes on the
   connector lines are the reason: at .5s per cycle every frame catches them at a different offset,
   so a stitched image shows the same line with its dashes jumping at each seam. Killing the
   animation parks stroke-dashoffset at 0, which is identical in every frame.
   Blanket rather than per-rule, so an animation added later cannot quietly reintroduce the problem. */
body.flatten *,
body.flatten *::before,
body.flatten *::after { animation: none !important; transition: none !important; }
/* a row caught mid-glow should still read as highlighted rather than blink out, so it takes the
   same static appearance the reduced-motion fallback uses */
body.flatten tr.r-glow > td { border-color: #f5ecff;
  box-shadow: 0 0 0 1px #f0e4ff, 0 0 3px #faf5ff, 0 0 18px var(--settle-line),
              inset 0 0 12px color-mix(in srgb, var(--settle-line) 38%, transparent); }
body.flatten #flatbtn { background: var(--good); color: #fff; border-color: var(--good); }
.flatnote { font-size: 12px; color: var(--good); margin-right: 10px; }
.flatnote:empty { display: none; }

/* the preview's quiet indicator, for when the bar has been dismissed */
.authnote.au-preview { color: #b45309; font-weight: 600; }
.sync-bad { color: var(--critical); font-weight: 600; }
/* Ethan owes the WHOLE amount of this one, not a share of it. Amber to match the left bar that
   already marks a full-cost row, and it says 100% rather than carrying an ambiguous "!". */
.fullchip { display: inline-block; margin-left: 6px; padding: 0 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; vertical-align: middle; text-decoration: none;
  color: #fff; background: #b45309; }
tr.r-closed .fullchip { opacity: .65; }
.ntchip:empty { display: none; }
.ntchip { display: inline-block; margin-left: 5px; padding: 0 6px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; vertical-align: middle;
  color: var(--series-1); background: color-mix(in srgb, var(--series-1) 15%, transparent); }
.rpx-foot { margin-top: 8px; color: var(--muted); font-size: 11px; font-style: italic; }
#rowpanel:not(.locked) .rpx-acts { opacity: .75; }
tr.rp-open > td { background: color-mix(in srgb, var(--series-1) 10%, transparent) !important; }
#rp-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 32;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#rp-backdrop[hidden] { display: none !important; }
#rp-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(820px, 96vw); max-height: 92vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.4); }
.rp-tabs { display: flex; gap: 6px; margin: 8px 0 6px; }
.rp-tab.on { background: var(--series-1); border-color: var(--series-1); color: #fff; }
.rp-tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; margin-top: 8px; }
.rp-tbl th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); font-weight: 600; padding: 4px 6px; }
.rp-tbl td { padding: 5px 6px; border-bottom: 1px solid color-mix(in srgb, var(--border) 45%, transparent); }
.rp-tbl code { background: color-mix(in srgb, var(--series-1) 12%, transparent); padding: 1px 6px;
  border-radius: 5px; font-size: 12px; }
.rp-add { display: flex; gap: 6px; margin-top: 10px; flex-wrap: wrap; }
.rp-add input { flex: 1 1 200px; padding: 5px 8px; border: 1px solid var(--border);
  border-radius: 7px; background: var(--page); color: var(--text-primary); font-size: 12.5px; }
#settle-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 31;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#settle-backdrop[hidden] { display: none !important; }
#settle-modal { background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border);
  border-radius: 14px; padding: 18px; width: min(900px, 96vw); max-height: 92vh; overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0,0,0,.4); }
#su-go:disabled { opacity: .45; cursor: not-allowed; }
.su-tbl tr.su-part td { background: color-mix(in srgb, #b45309 10%, transparent); }
.su-partnote { color: #b45309; font-weight: 600; }
.su-whynote { color: var(--muted); font-style: italic; }
.su-left { color: #b45309; font-weight: 600; }
.su-note { color: var(--muted); font-style: italic; }
/* jump to the reimbursement an item belongs to, and flash it on arrival */
.jumpchip { display: inline-block; margin-left: 5px; padding: 0 7px; border-radius: 999px;
  border: 1px solid var(--settle-line); color: var(--settle-line); font-size: 10.5px;
  cursor: pointer; white-space: nowrap; }
.jumpchip:hover { background: color-mix(in srgb, var(--settle-line) 16%, transparent); }
/* Arriving at a reimbursement: the cell's EDGE lights like a neon tube and breathes, one second
   per breath, three times. Layered shadows do the tube: a near-white core at the glass, then
   widening purple halos outside it and one bleeding inwards. The fill is left alone on purpose —
   it is the edge that should read as lit, not the row as highlighted. */
@keyframes neontube {
  /* Rest state is the cell EXACTLY as it normally sits, so each breath starts and ends on the
     real border and the row never appears to be swapped for a different one. */
  0%, 100% {
    border-color: color-mix(in srgb, var(--settle-line) 45%, transparent);
    box-shadow: 0 0 0 0 transparent, inset 0 0 0 transparent;
  }
  50% {
    border-color: #f5ecff;
    box-shadow:
      0 0 0 1px #f0e4ff,          /* spread, not width: thickens the tube without reflowing */
      0 0 3px #faf5ff,
      0 0 8px color-mix(in srgb, var(--settle-line) 95%, white),
      0 0 18px var(--settle-line),
      0 0 34px color-mix(in srgb, var(--settle-line) 72%, transparent),
      0 0 56px color-mix(in srgb, var(--settle-line) 40%, transparent),
      inset 0 0 12px color-mix(in srgb, var(--settle-line) 38%, transparent);
  }
}
/* NB: no border-width change here. Border width is layout, so animating it shifts the text and
   reads as the cell being replaced rather than lit. Only colour and shadow may move. */
tr.r-glow > td { animation: neontube 1s ease-in-out 3; }
/* Steady neon on every row of a reimbursement while one of them is selected: the payment, the
   placeholder, Ethan's counted expenses and Stephanie's covered claims all light at once, so the
   whole relationship is visible without tracing anything. */
tr.r-lit > td { border-top: 1px solid var(--settle-line); border-bottom: 1px solid var(--settle-line);
  background: color-mix(in srgb, var(--settle-line) 12%, transparent) !important;
  box-shadow: 0 0 6px color-mix(in srgb, var(--settle-line) 45%, transparent); }
tr.r-lit > td:first-child { border-left: 1px solid var(--settle-line); }
tr.r-lit > td:last-child { border-right: 1px solid var(--settle-line); }
/* The hop back out of the placeholder. It used to be a 46px outline chip wedged between the
   ⇄ reimbursement badge and ✖ undo, and it read as part of that cluster rather than as the way
   back, so it went unnoticed. Filled, and it names its destination. */
.jumpback { border-color: var(--settle-line) !important; background: var(--settle-line) !important;
  color: #fff !important; font-weight: 600; padding: 2px 9px !important; }
.jumpback:hover { filter: brightness(1.15); }
.jumpback .jb-to { font-weight: 400; opacity: .92; }
.jumpback[hidden] { display: none !important; }
@media (prefers-reduced-motion: reduce) {
  tr.r-glow > td { animation: none; border-color: #f5ecff;
    box-shadow: 0 0 0 1px #f0e4ff, 0 0 3px #faf5ff, 0 0 18px var(--settle-line),
                inset 0 0 12px color-mix(in srgb, var(--settle-line) 38%, transparent); } }
/* a partly cancelled item still owes something, so it stays present rather than struck through */
tr.r-partcancel td:first-child { box-shadow: inset 3px 0 0 #b45309; }
#su-list { max-height: 46vh; overflow-y: auto; margin-top: 6px; }
.su-tbl { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.su-tbl th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); font-weight: 600; padding: 4px 6px; }
.su-tbl td { padding: 4px 6px; border-bottom: 1px solid color-mix(in srgb, var(--border) 45%, transparent); }
.su-tbl tr.di-off td { opacity: .4; }
.su-sum { margin-top: 8px; font-size: 12.5px; line-height: 1.6; }
.su-sum .su-net { font-weight: 700; }
.su-ok { color: var(--good); font-weight: 600; }
.su-short { color: var(--critical); font-weight: 600; }
.di-net.di-net-info { background: var(--surface-2, var(--page)); border-color: var(--border);
  color: var(--text-secondary); }
.di-net[hidden] { display: none !important; }
.di-net .rbtn { margin-left: 6px; }
.dist-btn { border-color: var(--chip-h) !important; color: var(--chip-h) !important; }


/* ============================================================
   RESPONSIVE: keep every description readable on smaller displays
   The three data columns are a FIXED 334px block (96+150+62+26) and the
   description takes whatever is left, truncating with an ellipsis. That block
   does not shrink, so every pixel lost to a narrower screen comes out of the
   description alone. Measured on the live app before this change:

     1920  ->  1 truncated description     1366  ->  31      (only 2 rows on screen)
     1600  ->  4                           1280  -> 122
     1440  ->  6                           1024  -> 511      (+5px sideways scroll)

   Fixes, in order of how little they cost: let the description WRAP instead of
   truncating, shrink the fixed block, then stack the two columns.
   ============================================================ */

/* ---- a long description wraps instead of being cut off, at EVERY width.
   Nothing is ever hidden; a cramped row just gets taller. Even 1920 and 1600
   truncated a few rows, and a truncated payee is exactly the thing someone is
   trying to read. ---- */
.recon-pane td.prime {
  white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
@media (max-width: 1599px) {
  .recon-pane tr.r-row td { line-height: 1.5; vertical-align: top; }
}

/* ---- 1251-1599: claw width back for the description by tightening the fixed
   block and the gutter, so most rows still fit on one line ---- */
@media (min-width: 1251px) and (max-width: 1599px) {
  .recon-pair, .recon-headrow { gap: 24px; }
  main { padding: 12px 14px 56px; }
  .recon-pane th:nth-child(2), .recon-pane td[data-l="value"] { width: 86px; }
  .recon-pane th:nth-child(3), .recon-pane td[data-l="src"]   { width: 112px; }
  .recon-pane th:nth-child(4), .recon-pane td[data-l="date"]  { width: 54px; }
  .recon-pane td[data-l], .recon-pane th:nth-child(2),
  .recon-pane th:nth-child(3), .recon-pane th:nth-child(4) { padding-left: 6px; }
  .recon-pane td[data-l="src"] { font-size: 11px; }
  .recon-pane { padding: 8px 10px; }
}

/* ---- 1250 and below: two columns no longer fit side by side, so stack them.
   Each pane then owns the full width. Raised from 900px, which left 1024 and
   1152 in a two-column layout with only ~108px for the description. ---- */
@media (max-width: 1250px) {
  .recon-pair, .recon-headrow { grid-template-columns: 1fr; gap: 10px; }
  #recon-svg { display: none; }
  .recon-headrow { position: static; }
  .recon-headcol { text-align: left; }
  .pane-cap { display: block; font-weight: 700; font-size: 13px;
    margin: 2px 0 6px; color: var(--text-secondary); }
  main { padding: 12px 12px 56px; }
}

/* Touch-sized buttons are about the POINTER, not the window: a 1024px desktop
   window driven by a mouse wants dense rows, a tablet wants fat targets. */
@media (max-width: 1250px) and (pointer: fine) { .rbtn { padding: 3px 7px; font-size: 11px; } }
@media (max-width: 1250px) and (pointer: coarse) { .rbtn { padding: 7px 12px; font-size: 12px; } }

/* ---- phones: the fixed column widths total 334px plus padding, which is wider
   than the screen itself, so the table pushed the whole PAGE sideways (179px of
   horizontal scroll measured at 390px). Let the columns size themselves. ---- */
@media (max-width: 720px) {
  .recon-pane th:nth-child(2), .recon-pane td[data-l="value"] { width: 74px; }
  .recon-pane th:nth-child(3), .recon-pane td[data-l="src"]   { width: 78px; }
  .recon-pane th:nth-child(4), .recon-pane td[data-l="date"]  { width: 46px; }
  .recon-pane td[data-l], .recon-pane th { white-space: normal; overflow: visible;
    text-overflow: clip; overflow-wrap: anywhere; padding-left: 5px; font-size: 11px; }
  .recon-pane td.prime { font-size: 12.5px; }
}

/* never let the page itself scroll sideways. Deliberately NOT overflow-x:hidden
   on html/body: that makes body a scroll container and kills the sticky header,
   column headers and tally bar. Constrain the grid children instead. */
.recon-pair > *, .recon-headrow > * { min-width: 0; }
#recon-wrap { max-width: 100%; }

/* ---- short viewports: a 768px-tall laptop was spending its whole screen on
   chrome. Measured at 1024x768 before this: toolbar 175px + two column header
   cards 160px + month header 75px + tally bar 160px, leaving no room for a
   single ledger row. Tighten the furniture, touch nothing structural. ---- */
@media (max-height: 820px) {
  header { padding: 6px 16px; }
  .brand { font-size: 15px; }
  main { padding-top: 10px; }
  .panel { padding: 9px 12px; margin: 9px 0; }
  .recon-controls { gap: 10px 14px; font-size: 12.5px; }
  .recon-headcol { padding: 6px 10px; }
  .colfilter { margin-top: 4px; }
  .colfilter input, .colfilter select { padding: 3px 7px; }
  .recon-month { margin: 9px 0 14px; }
  details.recon-month > summary { margin: 4px 0; padding-bottom: 3px; }
  .eomstrip { font-size: 10.5px; }
  #tallybar { padding: 7px 12px; }
}

/* the filter result chip ("53 shown · $32,651.71") is nowrap and was the one
   element pushing the whole page sideways on a phone (13px past the viewport) */
@media (max-width: 720px) {
  .colfilter { flex-wrap: wrap; }
  .colfilter .fcount { white-space: normal; }
}
/* counterparty / provenance chips are nowrap, which sets the description
   column's minimum width and clipped it on a phone */
@media (max-width: 720px) {
  .xferchip, .provchip { white-space: normal; }
}

/* ============================================================
   MOBILE GATE
   Below 1250px the two columns stack, which means Ethan's ~1,200 rows and THEN
   Stephanie's. That is not a reconciliation, it is two lists, and every modal
   covers the whole screen. Rather than ship a layout that cannot do the job,
   touch devices that are too narrow for the side-by-side view get a notice.

   Scoped to (pointer: coarse) and (hover: none), i.e. an actual phone or
   tablet. A narrow DESKTOP window is deliberately NOT gated: that user can just
   widen the window, and the stacked layout works fine for them. An iPad in
   landscape (1366px) gets the real app; rotated to portrait (1024px) it gets
   the notice, which is why the copy mentions turning the device.
   ============================================================ */
#mobile-gate { display: none; }
@media (max-width: 1250px) and (pointer: coarse) and (hover: none) {
  /* unconditional: no dismissed-state selector, so there is no combination of
     clicks or stored flags that reveals the app underneath */
  #mobile-gate {
    display: flex; position: fixed; inset: 0; z-index: 500;
    align-items: center; justify-content: center; padding: 24px;
    background: var(--page); color: var(--text-primary); }
  /* opaque and full-bleed above, and the page behind must not scroll. Both
     elements: the scrolling element is <html>, so body alone still let a touch
     drag move the document under the overlay (iOS rubber-banding can expose
     that at the edges). */
  html, body { overflow: hidden; height: 100%; }
  .mg-card { max-width: 420px; text-align: center; }
  .mg-icon { font-size: 40px; line-height: 1; margin-bottom: 14px; }
  .mg-card h1 { font-size: 20px; line-height: 1.3; margin: 0 0 14px; }
  .mg-card p { color: var(--text-secondary); font-size: 14px; line-height: 1.55; margin: 0 0 12px; }
}
