/* Meraki CRM — shared stylesheet.
   Extracted from the approved mockups. No build step: served directly. */

:root {
  --navy: #1b5772;
  --navy-deep: #123c50;
  --navy-ink: #0d2c3b;
  --gold: #f0b45f;
  --gold-deep: #d99a3e;
  --gold-soft: #fdf3e3;
  --paper: #f4f6f7;
  --line: #e3e8ea;
  --muted: #7b8a92;
  --ink: #1c2b33;
  --ok: #2e7d46;
  --ok-soft: #e7f3ea;
  --warn: #b3690f;
  --warn-soft: #fdf0dc;
  --bad: #b3372e;
  --bad-soft: #fbe9e7;
  --sidebar-w: 236px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: 'Archivo', -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--paper);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

.mono { font-family: 'IBM Plex Mono', ui-monospace, monospace; }
/* On an input this needs the same specificity as the shared input rule, which
   sets font-family:inherit — otherwise the VIN, contract number and registration
   fields are not monospaced at all, which is the one place it matters. */
input.mono, textarea.mono { font-family: 'IBM Plex Mono', ui-monospace, monospace; }
a { color: var(--navy); }

/* ---------- Sidebar ---------- */
.sidebar {
  position: fixed; inset: 0 auto 0 0; width: var(--sidebar-w);
  background: linear-gradient(180deg, var(--navy-ink), var(--navy-deep));
  color: #fff; display: flex; flex-direction: column; z-index: 20;
}
.sidebar-logo { padding: 14px 20px; background: #fff; }
.sidebar-logo img { width: 118px; display: block; margin: 0 auto; }
.sidebar-nav { flex: 1; padding: 10px 0 14px; overflow-y: auto; }
.section-label {
  padding: 16px 22px 6px; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: 1.6px; color: rgba(255,255,255,.35);
}
.sidebar-nav a {
  display: flex; align-items: center; gap: 11px; padding: 9px 22px;
  color: rgba(255,255,255,.66); text-decoration: none; font-size: 13.5px;
  border-left: 3px solid transparent; transition: all .15s;
}
.sidebar-nav a:hover { color: #fff; background: rgba(255,255,255,.05); }
.sidebar-nav a.active {
  color: #fff; background: rgba(240,180,95,.12);
  border-left-color: var(--gold); font-weight: 600;
}
/* Not-yet-built sections. Visibly inactive, and not clickable — they show the
   shape of what is coming without pretending to be a working link. */
.sidebar-nav .nav-soon {
  display: flex; align-items: center; gap: 11px; padding: 9px 22px;
  color: rgba(255,255,255,.28); font-size: 13.5px;
  border-left: 3px solid transparent; cursor: default; user-select: none;
}
.sidebar-nav .nav-soon .nav-icon { opacity: .5; }
.sidebar-nav .nav-soon .phase {
  margin-left: auto; font-size: 9.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: rgba(255,255,255,.34);
  border: 1px solid rgba(255,255,255,.16); border-radius: 3px; padding: 1px 5px;
}

.nav-icon { width: 18px; text-align: center; font-size: 14px; }
.nav-count {
  margin-left: auto; background: var(--gold); color: var(--navy-ink);
  font-size: 10.5px; font-weight: 700; border-radius: 9px; padding: 1px 7px;
}
.sidebar-user {
  padding: 14px 20px; border-top: 1px solid rgba(255,255,255,.1);
  display: flex; align-items: center; gap: 11px;
}
.avatar {
  width: 34px; height: 34px; border-radius: 50%; background: var(--gold);
  color: var(--navy-ink); display: flex; align-items: center;
  justify-content: center; font-weight: 800; font-size: 12.5px; flex-shrink: 0;
}
.user-name { font-size: 13px; font-weight: 600; }
.user-role { font-size: 11px; color: rgba(255,255,255,.45); }
.sidebar-user form { margin-left: auto; }
.sidebar-user button {
  background: none; border: none; color: rgba(255,255,255,.45);
  cursor: pointer; font-size: 15px; padding: 4px;
}
.sidebar-user button:hover { color: #fff; }

/* ---------- Main + topbar ---------- */
.main { margin-left: var(--sidebar-w); min-height: 100vh; }
/* The search and the tabs, stuck to the top together.

   "When you select a tab the top of screen is the start of the white page
   content — you have to scroll up to see the tabs."

   Sticky on the wrapper rather than on each of them: the topbar wraps to two
   rows on a narrow screen, so any fixed offset given to the strip below would
   be wrong on exactly the screen where the room matters. */
.chrome { position: sticky; top: 0; z-index: 10; }

.topbar {
  background: #fff; border-bottom: 1px solid var(--line); padding: 13px 28px;
  display: flex; align-items: center; gap: 18px;
  justify-content: flex-end;
}
.topbar .search { margin-right: auto; }
.topbar h1 {
  font-size: 18px; font-weight: 700; color: var(--navy-ink);
  letter-spacing: -.2px; margin-right: auto;
}
/* On a record page the crumb IS the page heading — there is no <h1> beside it.
   At 12.5px grey it was smaller than the body text underneath, so the name of
   the thing you were looking at was the least prominent thing on the screen. */
.crumb {
  font-size: 17px; font-weight: 700; color: var(--navy-ink);
  margin-right: auto; letter-spacing: -.2px; line-height: 1.35;
}
.crumb a {
  text-decoration: none; font-weight: 600; color: var(--muted); font-size: 14px;
}
.crumb a:hover { color: var(--navy); }
.crumb .crumb-sep { color: var(--line); font-weight: 400; margin: 0 2px; }
.search { position: relative; flex: 0 1 430px; }
.search input {
  width: 100%; padding: 10px 14px 10px 38px; border: 1.5px solid var(--line);
  border-radius: 10px; font-family: inherit; font-size: 13px; outline: none;
  background: var(--paper); transition: all .2s;
}
.search input:focus { border-color: var(--navy); background: #fff; }
.search::before {
  content: '⌕'; position: absolute; left: 13px; top: 6px;
  font-size: 17px; color: var(--muted);
}
.content { padding: 24px 28px 44px; }

/* ---------- Tab strip ---------- */
/* Wraps onto a second row rather than scrolling sideways. A tab you cannot see
   is a tab you forget you have open, which defeats the point of keeping them. */
/* F3 — the strip was running to three rows and taking a quarter of the screen.

   Three things did that, and all three are here: tabs were 12px with generous
   padding, labels never truncated — a deal tab reads "MF-0660 · The Trustee for
   The Brown Family Trust · 2022 Kenworth" and three of those fill a row — and
   the strip wrapped as far as it liked.

   Two of those three still hold, and they are what made the third unnecessary:
   the tabs are small and the labels truncate, so a row costs far less than it
   did when F3 was written.

   The height cap does not hold any more.

   "I have three rows of tabs and only two show without scrolling the tab bar up
   and down — it should push page content down as new rows add."

   A capped strip scrolls inside itself, which means the row you want is behind a
   scrollbar you have to notice, inside a bar that is not where anybody looks for
   a scrollbar. A tab exists to be seen; one you have to go hunting for is not
   doing its job. So the strip wraps as far as it needs and the page starts
   underneath it — every tab visible, always.

   What this costs: at a great many tabs the strip grows without limit. Nothing
   discards them (see TAB_CEILING in the partial, which is a runaway-script
   guard rather than a tidiness rule), so the answer to a strip that has grown
   too tall is to close some — which is a thing you can see and do, unlike a
   hidden third row. */
.tabstrip {
  display: flex; align-items: flex-end; flex-wrap: wrap;
  column-gap: 3px; row-gap: 3px;
  background: var(--navy-deep); padding: 7px 18px 0;

  /* No cap, deliberately, and it is now a sticky one.

     "I have three rows of tabs and only two show without scrolling the tab bar
     up and down — it should push page content down as new rows add."

     F3 capped this at two rows and let it scroll inside itself, and that is the
     thing he asked to have taken off: a tab behind a scrollbar in a bar nobody
     thinks to scroll is a tab he kept on purpose and cannot see. Sticky makes
     the cap more tempting, not less wrong — three rows of tabs he can read beat
     two rows and a hidden one, and what keeps a row cheap is the other half of
     F3, small tabs and truncated labels. */
}

/* Anything jumped to by an anchor clears the sticky header. Without this,
   #assets-and-liabilities lands the panel heading underneath the tabs and reads
   as having gone to the wrong place. Generous, because the header's height
   depends on how many tabs are open. */
:target { scroll-margin-top: 190px; }

.tab {
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 9px 6px;
  font-size: 11.5px; font-weight: 600; color: rgba(255,255,255,.72);
  background: rgba(255,255,255,.07); border-radius: 8px 8px 0 0;
  white-space: nowrap; cursor: pointer; text-decoration: none;
}
/* The title attribute already carries the whole thing, so nothing is lost —
   and the deal number leads the label, which is why it truncates from the
   right without costing him the one part he needs.

   A fixed width rather than a maximum, so every tab is the same size and the
   close button is always in the same place:

     "When I want to get rid of it and start closing, I'm gonna start doing
      this, but if they're the same size, could be handy… when I'm doing this,
      I'm just clicking close, close."

   He shuts three or four in a row, and with the width following the label the X
   moved a little to the left each time and the next click landed on the tab
   instead of its button.

   The tab he is on used to be given a wider label on the reasoning that it
   earned the room — our reasoning, not his, and it measured 273px against 177px
   for the rest. "Top tab for Applications is oversized." On a strip three rows
   deep one swollen tab among a dozen even ones is what the eye lands on, and it
   costs the close buttons their alignment on that row. Every tab is the same
   size now, whichever one you are on. */
.tlabel {
  width: 132px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tab:hover { background: rgba(255,255,255,.14); color: #fff; }
/* Fixed, like the label: the tab you are on is bold, and a bold glyph is wider
   than a light one — enough to put its close button eight pixels out of line
   with the row it sits in, which is the alignment the fixed label was for. */
.tab .tico { font-size: 11px; color: var(--gold); flex: 0 0 12px; text-align: center; }
/* "The X button's small… they're so small that you could probably just switch to
   it by accident, and it's not doing" what you meant. A bigger hit area rather
   than a bigger glyph — the strip stays the same height. */
.tab .x {
  color: rgba(255,255,255,.35); margin-left: 2px; font-size: 14px; line-height: 1;
  padding: 1px 0; margin-right: -3px; border-radius: 4px;
  flex: 0 0 18px; text-align: center;
}
.tab .x:hover { color: #fff; background: rgba(255,255,255,.16); }
.tab.on .x:hover { color: var(--bad); background: rgba(0,0,0,.06); }
.tab.on {
  background: var(--paper); color: var(--navy-ink);
  box-shadow: inset 0 3px 0 var(--gold); font-weight: 700;
}
.tab.on .tico { color: var(--gold-deep); }
.tab.on .x { color: var(--muted); }

/* ---------- Buttons ---------- */
.btn {
  padding: 9px 15px; border-radius: 9px; font-family: inherit; font-size: 13px;
  font-weight: 700; cursor: pointer; border: none; transition: all .15s;
  white-space: nowrap; text-decoration: none; display: inline-block;
}
/* A button that cannot be pressed has to look like one, or it reads as a button
   that is broken. */
.btn[disabled] { opacity: .45; cursor: default; }
.btn[disabled]:hover { background: inherit; }

.btn-gold { background: var(--gold); color: var(--navy-ink); }
.btn-gold:hover { background: var(--gold-deep); }
.btn-navy { background: var(--navy); color: #fff; }
.btn-navy:hover { background: var(--navy-deep); }
.btn-outline { background: #fff; color: var(--navy); border: 1.5px solid var(--navy); }
.btn-sm { padding: 6px 11px; font-size: 12px; border-radius: 8px; }
.btn-block { width: 100%; text-align: center; }

/* ---------- Panels ---------- */
.panel {
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  overflow: hidden; margin-bottom: 18px;
}
.panel-head {
  padding: 10px 16px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 10px;
}
/* A choice that belongs to a whole panel, stated on its heading line rather
   than as another field inside it — "to the right hand side in the header box
   for Commission". */
.head-check {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--muted); cursor: pointer; white-space: nowrap;
}
.head-check input { margin: 0; cursor: pointer; }
.head-check:hover { color: var(--ink); }

.panel-head h3 {
  font-size: 14.5px; font-weight: 700; color: var(--navy-ink); margin-right: auto;
}
/* A form in a panel head is a control, not a paragraph. display:inline left it
   on the text baseline while the buttons either side sat on their own. */
.head-action { display: inline-flex; align-items: center; }
/* .meta was scoped to .panel-head, so the same class used anywhere else fell
   back to the body size and came out larger than the text around it — most
   visibly on the deal's parties panel. It is a general "secondary text" class
   and is now defined as one. */
.meta { font-size: 12px; color: var(--muted); }
.panel-body { padding: 11px 16px; }
/* Buttons wearing this class kept carrying font:inherit, which took the panel
   heading's size — Clone, Edit on a business, and + Previous address all came
   out oversized. The font is stated here so the inline override is never
   needed. */
.link {
  font-family: inherit; font-size: 12.5px; line-height: 1.4;
  color: var(--navy); font-weight: 600; text-decoration: none;
}
/* A button that says it is a link has to stop looking like a button. Nine views
   said so a tenth of an inch at a time, each carrying its own
   style="background:none;border:none" — this is that rule, once. */
button.link {
  background: none; border: none; padding: 0; cursor: pointer;
}

/* ---------- Stat cards ---------- */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 22px; }
.stat {
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  padding: 18px 20px 16px; position: relative; overflow: hidden;
}
.stat::after {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: 4px; background: var(--navy);
}
.stat.gold::after { background: var(--gold); }
.stat.warn::after { background: var(--bad); }
.stat-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 1.2px;
  color: var(--muted); font-weight: 600;
}
.stat-value {
  font-size: 27px; font-weight: 800; color: var(--navy-ink); margin-top: 6px;
  letter-spacing: -.5px; font-variant-numeric: tabular-nums;
}
.stat-sub { font-size: 12px; color: var(--muted); margin-top: 3px; }

/* ---------- Tables ---------- */
table { width: 100%; border-collapse: collapse; }
th {
  text-align: left; padding: 9px 16px; font-size: 10.5px; font-weight: 700;
  color: var(--muted); text-transform: uppercase; letter-spacing: .8px;
  background: #fafbfc; border-bottom: 1px solid var(--line);
}
td { padding: 11px 16px; font-size: 13px; border-bottom: 1px solid #f0f2f3; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: #fafbfc; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.cell-main { font-weight: 600; color: var(--ink); }
.cell-sub { font-size: 11.5px; color: var(--muted); margin-top: 1px; }

/* The name is the link, not the row.
 *
 * "For Individuals, Businesses, Contacts, Lenders and Suppliers make the name
 * only the link — highlighting text to copy keeps opening tabs on them."
 *
 * A click handler on the row fires when a selection drag ends anywhere inside
 * it, so dragging across an ABN to copy it opened the record instead — and in
 * this application opening a record is a new tab in the strip. The name carries
 * the link now and the rest of the row is text you can select.
 *
 * It has to look like the text it replaced: cell-main is what the name was, and
 * a link that announced itself in blue would make every list look like a page
 * of links rather than a table with a way in.
 */
a.row-link { color: inherit; text-decoration: none; }
a.row-link:hover {
  text-decoration: underline; text-decoration-color: var(--gold);
  text-underline-offset: 2px;
}

/* ---------- Pills ---------- */
.pill {
  display: inline-block; padding: 2.5px 9px; border-radius: 10px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .4px;
}
.p-ok { background: var(--ok-soft); color: var(--ok); }
.p-warn { background: var(--warn-soft); color: var(--warn); }
.p-bad { background: var(--bad-soft); color: var(--bad); }
.p-neutral { background: #e8eef1; color: var(--navy); }
/* dormant, and never-dealt: quiet rather than alarming — neither is a failure */
.p-quiet { background: #f1f3f5; color: #8b949e; }

/* ---------- Forms ---------- */
/* Forms are denser than they were.
   "When the Application is edited the form that opens is too large — condense
   it to nearer the size it displays unedited", and the same complaint again on
   a person's edit form. The read-only view of a record is compact; the form was
   nearly twice as tall for the same content, so a deal that reads on one screen
   took three to edit. Changed here rather than per form so every one of them
   comes down together and they stay consistent. */
.field { margin-bottom: 9px; }
label {
  display: block; font-size: 11.5px; font-weight: 600; color: var(--navy-deep);
  margin-bottom: 2px; letter-spacing: .3px;
}
/* `input:not([type])` is the important one. An input written without a type
   attribute is a text input by spec, but `input[type=text]` never matches it —
   so 31 of the 54 inputs in this app were falling through to browser defaults,
   small and square and unstyled. That single omission was behind three separate
   complaints about fields being "too small".
   Specificity is deliberately kept at (0,1,1), the same as before: a :not()
   chain would have outranked `.search input` and broken the search box. */
input[type=text], input[type=email], input[type=password], input[type=tel],
input[type=date], input[type=datetime-local], input[type=number],
input:not([type]),
select, textarea {
  width: 100%; padding: 6px 10px; border: 1.5px solid var(--line);
  border-radius: 7px; font-family: inherit; font-size: 13.5px; outline: none;
  transition: border .2s; background: #fff; color: var(--ink);
}
input:focus, select:focus, textarea:focus { border-color: var(--navy); }
.field-error { color: var(--bad); font-size: 12px; margin-top: 3px; }
input.has-error { border-color: var(--bad); }
.field-hint { color: var(--muted); font-size: 11px; margin-top: 2px; }

/* ---------- Alerts ---------- */
.alert {
  padding: 12px 15px; border-radius: 10px; font-size: 13px; margin-bottom: 18px;
  border: 1px solid transparent;
}
.alert-ok { background: var(--ok-soft); color: var(--ok); border-color: #cfe3d6; }
.alert-warn { background: var(--warn-soft); color: var(--warn); border-color: #ecc9a1; }
.alert-bad { background: var(--bad-soft); color: var(--bad); border-color: #e4b0aa; }

/* ---------- Auth pages ---------- */
.auth-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background:
    radial-gradient(1100px 600px at 85% -10%, rgba(240,180,95,.16), transparent 60%),
    radial-gradient(900px 700px at -10% 110%, rgba(27,87,114,.20), transparent 55%),
    linear-gradient(160deg, #0d2c3b 0%, #123c50 45%, #1b5772 100%);
}
.auth-frame { width: 100%; max-width: 420px; }
.auth-card {
  background: #fff; border-radius: 14px; padding: 40px 36px 32px;
  box-shadow: 0 30px 60px -18px rgba(13,44,59,.55);
  animation: rise .5s cubic-bezier(.2,.8,.25,1) both;
}
@keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.auth-logo { display: block; width: 170px; margin: 0 auto 10px; }
.auth-tag {
  text-align: center; font-size: 11.5px; letter-spacing: 2.5px;
  text-transform: uppercase; color: var(--muted); margin-bottom: 24px;
}
.auth-rule {
  height: 4px; width: 56px; margin: 0 auto 26px; border-radius: 2px;
  background: linear-gradient(90deg, var(--navy) 0 50%, var(--gold) 50% 100%);
}
.auth-card h2 {
  font-size: 18px; font-weight: 700; color: var(--navy-ink);
  margin-bottom: 6px; text-align: center;
}
/* Was .auth-card .lede — the 403, 404 and 500 pages use .lede without an
   auth-card, so their standfirst was unstyled. Same trap as .meta. */
.lede {
  font-size: 13px; color: var(--muted); text-align: center;
  margin-bottom: 22px; line-height: 1.5;
}
.auth-foot {
  text-align: center; margin-top: 20px; font-size: 11.5px; color: rgba(255,255,255,.55);
}
.auth-row {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 16px; font-size: 12.5px;
}

/* 2FA setup */
/* input. rather than !important: the shared input rule is (0,1,1) and a bare
   class is (0,1,0), which is what the !important was papering over. Matching the
   specificity says the same thing without spending an override. */
input.code-input {
  font-family: 'IBM Plex Mono', monospace; font-size: 20px;
  text-align: center; letter-spacing: 6px;
}

/* ---------- Empty states ---------- */
.empty { padding: 40px 20px; text-align: center; color: var(--muted); font-size: 13.5px; }
.empty strong { display: block; color: var(--ink); font-size: 15px; margin-bottom: 6px; }

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 820px) {
  .sidebar {
    inset: auto 0 0 0; width: 100%; height: auto; flex-direction: row;
    align-items: center; padding: 0 8px;
  }
  .sidebar-logo, .section-label, .sidebar-user .user-role { display: none; }
  .sidebar-nav {
    display: flex; overflow-x: auto; padding: 6px 0; flex: 1;
  }
  .sidebar-nav a {
    padding: 8px 12px; border-left: none; border-bottom: 3px solid transparent;
    font-size: 12px;
  }
  .sidebar-nav a.active { border-left: none; border-bottom-color: var(--gold); }
  .main { margin-left: 0; padding-bottom: 64px; }
  .topbar { padding: 11px 16px; flex-wrap: wrap; }
  .search { flex: 1 1 100%; order: 3; }
  .content { padding: 16px; }
  .stats { grid-template-columns: 1fr; }
  .tabstrip { padding: 6px 12px 0; }
}

/* ---------- Form layout ---------- */
[x-cloak] { display: none !important; }
/* The grid spaces its own items with `gap`, and carries the space to whatever
   follows it. Fields inside a grid therefore need no bottom margin of their own.
   
   This replaces `.panel-body .field:last-child { margin-bottom: 0 }`, which
   zeroed the margin on the last field of every grid ROW rather than the last
   field in the panel — so a row that did not fill its columns, or a field on its
   own, had nothing beneath it. */
.form-row-1, .form-row-2, .form-row-3, .form-row-4 {
  display: grid; gap: 10px; margin-bottom: 9px;
}
/* one field to a line, for the ones that are a sentence or open a list beneath
   themselves — it belongs to the family so the spacing is the family's */
.form-row-1 { grid-template-columns: 1fr; }
/* a count of dependents is two characters; it does not need half a panel */
.field-narrow { max-width: 120px; }

/* The lender list carried three columns of full email addresses, two of them
   usually empty, which was most of the page. One column, three labelled lines,
   and only the ones that exist. */
/* a BDM is a name, a phone number and sometimes a second name under it */
.lender-bdm { min-width: 190px; }

/* Label and address, a line each, the way the record page reads them back.
   The label column is fixed so the addresses line up under one another and the
   eye runs down them; the address takes what is left and may break, because an
   email address is one long word. */
.lender-emails { display: block; }
.lender-email-head, .lender-email-row {
  display: grid; grid-template-columns: 190px 1fr; gap: 8px; align-items: center;
}
.lender-email-head {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); font-weight: 700; margin-bottom: 4px;
}
.lender-email-row { margin-bottom: 6px; }
.lender-email-row input { width: 100%; }
@media (max-width: 700px) {
  .lender-email-head { display: none; }
  .lender-email-row { grid-template-columns: 1fr; gap: 4px; }
}

/* The Applications list.

   "Alternating row shading" and "settled rows are too widely spaced to read" —
   the same complaint from two directions: on a long settled list the eye loses
   which row it is on. The banding gives it something to hold, and the asset
   column takes the room the row was spending on height.

   The date sits in the row rather than under it: a bordered box on every line
   would draw more attention than the dates it carries. */
.col-asset { min-width: 220px; }

/* "Settled rows are too widely spaced to read" and "alternating row shading" —
   the same complaint twice: on a long settled list the eye loses which row it is
   on. Scoped to this list rather than every table on the site, because the
   spacing elsewhere is not what he was reading.

   The banding does the work the height was doing, so the row can be tighter. */
/* "Freeze the header row when scrolling."
   A sticky heading sticks to whatever scrolls it, so the table is given the
   scrolling to do: it holds its own height and the page around it stays still.
   Sticking to the window instead would need this table not to be in a scroller,
   and it has to be — the asset at the end is what he scrolls sideways for. */
#deals-list .list-scroll { max-height: calc(100vh - 270px); overflow: auto; }
#deals-list thead th {
  position: sticky; top: 0; z-index: 2;
  background: #fff; box-shadow: inset 0 -1px 0 var(--line);
}

/* Room to be read rather than squeezed into slivers.

   With ten columns and no widths the browser compressed the text ones to about
   a hundred pixels, so a company name wrapped to three lines and every row stood
   141px tall — which is the "too widely spaced" he was looking at. Given their
   own width they wrap once or not at all, and the row comes down with them. */
#deals-list th, #deals-list td { white-space: nowrap; }
#deals-list .col-business, #deals-list .col-individual,
#deals-list .col-asset { white-space: normal; }
#deals-list .col-business { min-width: 190px; }
#deals-list .col-individual { min-width: 140px; }
#deals-list .col-lender { min-width: 130px; }

#deals-list td { padding: 7px 16px; }
#deals-list tbody tr:nth-child(even) { background: #fafbfc; }
#deals-list tbody tr:hover { background: #f2f6fa; }
/* the second line under a company name is what made these rows tall */
#deals-list .cell-sub { margin-top: 0; line-height: 1.35; }
.col-due { white-space: nowrap; }

.due-inline {
  border: 1px solid transparent; background: none; padding: 1px 2px;
  font: inherit; font-size: 12px; color: inherit; width: auto;
}
.due-inline:hover { border-color: var(--line); background: #fff; }
.due-inline:focus { border-color: var(--navy); background: #fff; outline: none; }
.due-inline.due-overdue { color: var(--bad); font-weight: 600; }
.due-inline.due-today { color: var(--gold-deep); font-weight: 600; }

.lender-inboxes { font-size: 12px; line-height: 1.55; }
.lender-inboxes .inbox-for {
  display: inline-block; min-width: 96px;
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); font-weight: 700;
}
.form-row-2 { grid-template-columns: repeat(2, 1fr); }
.form-row-3 { grid-template-columns: repeat(3, 1fr); }
/* Where the first field holds something long — "Latitude Financial Services
   (Motor)" is thirty-five characters — and the other two hold a word each. */
.form-row-3.first-wide { grid-template-columns: 2fr 1fr 1fr; }
.form-row-4 { grid-template-columns: repeat(4, 1fr); }
.form-row-1 > .field, .form-row-2 > .field,
.form-row-3 > .field, .form-row-4 > .field { margin-bottom: 0; }

/* only the last thing in the panel loses its trailing space */
.panel-body > *:last-child { margin-bottom: 0; }
@media (max-width: 900px) {
  .form-row-2, .form-row-3, .form-row-4 { grid-template-columns: 1fr; }
}

/* The client band is gone.
 *
 * A navy header block above the record, carrying the name and a line of detail.
 * A business, a person and an application never had one; a contact and then a
 * supplier did, and on 29 August both lost it — "remove this header block to be
 * consistent with other pages". What it said lives in the crumb now.
 *
 * The rules went with it rather than being left to be picked up by accident and
 * put one page out of step again: .client-band, .client-id, .client-meta and
 * .ref-chip were all used by nothing else.
 */

/* ---------- Two-column record layout ---------- */
/* Both columns need min-width:0. A grid track sized 1fr still has min-width:auto
   on its item, so anything wide inside — a filename, a long business name, a
   table — pushes the column wider than the page instead of truncating in it. */
.layout { display: grid; grid-template-columns: 340px 1fr; gap: 18px; align-items: start; }
.layout > * { min-width: 0; }
@media (max-width: 1024px) { .layout { grid-template-columns: 1fr; } }

/* Equal columns, for panels that are read together rather than one after the
   other: guarantors beside documents, notepad beside tasks, and the three
   across the top of a person's page. Both collapse to one column on a narrow
   screen — a two-up layout squeezed into 400px is worse than a list. */
/* The edit form takes the same three columns as the panel it replaces, so
   opening Edit does not rearrange the page under him: the deal on the left, the
   loan in the middle, the asset and the commission stacked on the right.
   Explicit placement rather than flow, because the third column holds two. */
.deal-form .panel { margin-bottom: 0; }
.deal-form .panel-head { padding: 7px 16px; }
.deal-form .panel-head h3 { font-size: 12.5px; }

.deal-form .form-panels {
  display: grid; grid-template-columns: 1fr 1fr 1fr;
  gap: 12px; align-items: start;
}

/* Two columns, not three — on the new application only. The left is the client
   conversation — who is borrowing, then the money — and the right is the deal's
   own facts: asset, deal, commission. "It's jumping from page to page to page,
   and even me trying to help me explain it to you, I even got lost in where I
   was at and what I was doing." A third column was a third place to lose his
   place.

   Scoped to .deal-form-new: an application he already has keeps the three it
   has always had, because nothing about editing one changes. */
.deal-form-new .form-panels { grid-template-columns: 1fr 1fr; }

/* The asset and the commission are one column, grouped in the markup rather
   than placed by position. Two gains: the column is as tall as its contents —
   placing them in grid rows made the second start below a row sized by the
   deal panel, leaving a panel-high gap — and nothing depends on the panels
   staying in their current order. */
.form-col { display: contents; }
.deal-form .form-col {
  display: flex; flex-direction: column; gap: 12px; min-width: 0;
}

/* "Space above these too large."

   Not margins — every one of them was already zero. An empty child: the
   create-a-company panel is wrapped in a div that holds the entity type for the
   panels below it, and while "An existing client" is chosen that wrapper draws
   nothing. A flex gap applies on both sides of a child even when the child has
   no height, so the borrower panel and the client's panels were 12 + 12 apart
   while everything else in the column was 12.

   display:contents takes the wrapper out of the layout and leaves its contents
   in it, so the hidden fieldset inside is the child — and a hidden child takes
   no gap at all.

   The same for the region Apply fills. Empty it took a gap on each side while
   drawing nothing; full, its three panels were one child between them, so the
   column's spacing went round the group and they touched. As pass-through they
   are three children and get the twelve that everything else in the column
   gets. */
.deal-form .form-col > .is-passthrough,
.deal-form .form-col > #client-panels { display: contents; }

/* a narrow column is not the place for a three-across row */
.deal-form .form-panels .form-row-3,
.deal-form .form-panels .form-row-4 { grid-template-columns: 1fr 1fr; }

/* Except where the row is asked for three across by name.

   "Row 2: Year - Make - Model. Row 3: Registration - VIN - Engine / serial
   number." The rule above turned both into two-and-a-spare: Year and Make on
   one line, Model alone on the next, and the same again below it — which is
   what he sent back a picture of.

   The boxes are narrower than the rule was written to avoid. That is the trade
   he is making, and only these rows make it; every other three-across row in a
   deal panel still folds to two. Below 900 they go to one, like everything
   else. */
.deal-form .form-panels .form-row-3.is-thirds { grid-template-columns: repeat(3, 1fr); }

@media (max-width: 900px) {
  .deal-form .form-panels .form-row-3.is-thirds { grid-template-columns: 1fr; }
}

@media (max-width: 1200px) {
  .deal-form .form-panels { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 800px) {
  .deal-form .form-panels { grid-template-columns: 1fr; }
}

/* Fields the width of what goes in them. "The field for Year is 25% of row width
   — for what will be 4 characters? Purchase price could fit 40 digits. This is
   just wasted space making him scroll up and down." */
input.w-year { max-width: 6.5em; }
input.w-short { max-width: 8em; }
.deal-form input.money, .deal-form .unit-input { max-width: 13em; }
.deal-form .pair-inputs { max-width: 100%; }
.deal-form .pair-inputs .unit-input { max-width: none; }

/* The top of a deal: who is behind it, and what it is. "Company structure and
   guarantors top row to the left of the Application panel, which is now two
   thirds width." */
.deal-top { display: grid; grid-template-columns: 1fr 2fr; gap: 18px; align-items: start; margin-bottom: 18px; }
.deal-top > * { min-width: 0; }
@media (max-width: 1100px) { .deal-top { grid-template-columns: 1fr; } }

/* "Label and data on one line. Multiple columns / blocks of related data in
   each." Four blocks — what the deal is, what it is for, what it costs, what he
   earns — each a definition list in the same shape as a person's details. */
/* Three columns: the application, the loan, and the asset with what he earns on
   it underneath. Fixed at three rather than auto-fitting — he asked for these
   three, and auto-fit reflows to four on a wide screen and two on a laptop. */
.detail-blocks {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 2px 18px; padding: 6px 0 10px;
}
.detail-col { min-width: 0; }
@media (max-width: 1200px) { .detail-blocks { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 800px) { .detail-blocks { grid-template-columns: 1fr; } }
.detail-block { min-width: 0; }
.detail-block h4 {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--gold-deep); font-weight: 700; padding: 8px 16px 2px; margin: 0;
}
.detail-block .dl-row { padding: 4px 16px; }
.detail-block .dl-row dt { width: 92px; }

.pair, .trio { display: grid; gap: 18px; align-items: start; }
.pair { grid-template-columns: 1fr 1fr; }

/* Tasks beside the notepad, evenly.

   50/50 is the decision and it has been made twice. It was uneven originally,
   on the reasoning that the task table carries six columns and the notepad
   carries prose that reads fine at four hundred pixels; that was reset, and the
   comment describing the old arrangement was left behind still saying "not an
   even split", which is how I came to widen it back on the strength of a stale
   comment. It went to 55/45 briefly after that, chasing a Delete button that
   was being clipped, and went straight back once the clipping turned out to be
   a cell eight pixels narrower than the button inside it — nothing to do with
   this rule. See the Delete column in tasks/_table_head.

   Below 1200 they stack, because two columns of nothing much is worse than one
   of something. It was 1100, which left a band between 1100 and about 1200
   where the Task column came down to 57px — narrow enough that the assignee
   tag, one unbreakable box about 70px wide, hung out over Roll. Measured at
   1120: five rows of eight spilling. The title itself wraps and was never the
   problem. Only this pair moves; the other 1100s in this file are their own
   layouts with their own reasons. */
.pair-work { grid-template-columns: 1fr 1fr; }
@media (max-width: 1200px) { .pair-work { grid-template-columns: 1fr; } }
.trio { grid-template-columns: 1fr 1fr 1fr; }
.pair > *, .trio > * { min-width: 0; }
/* A panel that takes two of the three columns. At two columns it is the whole
   row, which is right: the structure reads on its own and compliance gets the
   width it needs for two lists side by side. */
.trio > .span-2 { grid-column: span 2; }

/* And one that takes the whole row.

     "I should have also asked to put the Record box underneath these three and
      give them full width."

   The documents panel took two of the three columns and Record sat in the
   third, so three document columns were run inside two thirds of the page and
   each got about 280px. Spanning all three gives them the page and drops Record
   underneath, which is where it belongs: it is read last and hardly read at
   all. Still span-2 elsewhere — this is the only panel that wants the lot. */
.trio > .span-3 { grid-column: 1 / -1; }

/* And Record does not stretch to fill what it is given. It is three dates and a
   delete button — "the Record box only needs to be small and left aligned, not
   full width" — so it takes what it needs and the rest of the row stays empty.
   justify-self, not a margin: the grid keeps the column, the panel just stops
   growing inside it. */
.record-small { max-width: 380px; justify-self: start; }

/* The three parts of the compliance panel: the deal's own paperwork, the
   identity documents of whoever signs, and everything else that was gathered to
   get it done. Chased from different places by different people, so they read
   better apart than interleaved.

   "Documents — separation between what's in the settlement pack and the
   supporting documents." A pack is a fixed set of four; supporting is whatever
   turned up. Filing them in one list put a BAS under a heading saying
   Settlement documents. */
.compliance-split { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 4px 14px; }

/* Three across held down to where a column stops being usable. The panel has
   the whole page now rather than half of it, so this sits much lower than it
   did: at a 1100px window the content is about 840px and each column still gets
   roughly 280, which the wrapped head handles. */
@media (max-width: 1100px) {
  .compliance-split { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 900px) {
  .compliance-split { grid-template-columns: 1fr; }
}
.compliance-split > * { min-width: 0; }
.split-head {
  padding: 10px 14px 0; font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
/* The compliance grid holds one kind of document now — the settlement pack — so
   it does not need the width of the screen. It wears .page-narrow like the task
   list, with the slots two to a row inside it. */

/* "Just have it in there saying unsigned contract." Its own line under the file
   input, because it is a sentence rather than a field. */
.slot-caveat { display: block; margin: 6px 0 8px; font-size: 12px; color: var(--muted); }
.slot-caveat span { display: block; margin-bottom: 3px; }
.slot-caveat input {
  width: min(420px, 100%); padding: 5px 8px; font-family: inherit; font-size: 12.5px;
  border: 1px solid var(--line); border-radius: 6px;
}
.slot-caveat input:focus { outline: none; border-color: var(--navy); }
.slots.slots-two-up { display: grid; grid-template-columns: 1fr 1fr; gap: 0 10px; }

@media (max-width: 1200px) {
}
@media (max-width: 900px) {
  .slots.slots-two-up { grid-template-columns: 1fr; }
}

/* a column with nothing in it still says so, rather than reading as a column
   that failed to load */
.split-none { padding: 8px 14px 12px; font-size: 12.5px; color: var(--muted); }

/* The compliance grid's filter bar: one thing to type into on the left, every
   chip flush right. "Move them flush right, and on the left have a search box." */
.compliance-filters {
  display: flex; gap: 12px; align-items: flex-start;
  flex-wrap: wrap; margin-bottom: 16px;
}
.compliance-chips {
  margin-left: auto; display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
}

.business-find { position: relative; flex: 0 1 320px; min-width: 220px; }
.business-search {
  width: 100%; padding: 7px 10px; font-family: inherit; font-size: 13px;
  border: 1px solid var(--line); border-radius: 7px; background: #fff;
}
.business-search:focus { outline: none; border-color: var(--navy); }

.business-list {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 4px);
  background: #fff; border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 10px 26px rgba(16, 34, 48, .16);
  max-height: 280px; overflow-y: auto; padding: 4px;
}
.business-option {
  display: block; padding: 6px 9px; font-size: 13px; color: var(--ink);
  text-decoration: none; border-radius: 5px;
}
.business-option:hover { background: var(--paper); color: var(--navy); }
.business-none { display: block; padding: 6px 9px; font-size: 12.5px; color: var(--muted); }

/* the chosen one, and the way back to all of them */
.business-chosen { display: inline-flex; align-items: center; gap: 8px; }
.business-clear { color: inherit; text-decoration: none; font-size: 15px; line-height: 1; opacity: .7; }
.business-clear:hover { opacity: 1; }

@media (max-width: 1280px) { .trio { grid-template-columns: 1fr 1fr; } }
/* grid-column: 1 / -1 follows the count down on its own, so span-3 stays the
   whole row at two columns and at one. */
@media (max-width: 1024px) { .compliance-split { grid-template-columns: 1fr; } }
@media (max-width: 1024px) { .pair, .trio { grid-template-columns: 1fr; } }

/* ---------- Definition lists ---------- */
.dl { padding: 6px 0; }
.dl-row { display: flex; padding: 7.5px 16px; font-size: 13px; }
.dl-row dt { width: 108px; color: var(--muted); flex-shrink: 0; }
/* A flex item will not shrink below its content unless it is told it may, and
   an email address is one long unbreakable word. Without these two the row grew
   to 399px inside a 338px panel and the address ran off the edge — "you can see
   that, how it's cut it off". The paired rows had both rules from the start;
   every other row on every record page did not. */
.dl-row dd { font-weight: 600; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }

/* Two to a line, where two belong together.

   "Let's make 2 rows in the Business details panel: Legal name Type / ABN ACN /
   ABN active from GST / Address / At address / Website / Phone Email."

   The panel now sits in the left column of an application as well as on the
   client's own page, and eleven single rows there is a tall thin thing to read
   past on the way to the loan.

   min-width:0 on the halves, or a long legal name refuses to wrap and pushes
   its partner off the end — the flex default is to size to content. Below 900
   they fall back to one per line, where half a column is not a column. */
.dl-pair { display: flex; }
.dl-pair > .dl-row { flex: 1 1 50%; min-width: 0; }

@media (max-width: 900px) { .dl-pair { display: block; } }
.src-note {
  font-size: 10.5px; color: var(--muted); background: #fafbfc;
  border-top: 1px solid var(--line); padding: 8px 16px;
}
.src-note b { color: var(--gold-deep); }

/* ---------- Document slots ---------- */
.slots { padding: 10px 12px 12px; display: grid; gap: 8px; }
/* min-width:0 on the grid item. A grid or flex item defaults to min-width:auto,
   which refuses to shrink below its content — so a long filename widened the
   slot past the panel no matter what its children did. The children needed it
   too; this is the one that was missing. */
.slots { min-width: 0; }
.slot {
  min-width: 0;
  display: flex; align-items: center; gap: 10px;
  border: 1.5px dashed var(--line); border-radius: 10px;
  padding: 9px 12px; font-size: 12.5px;
}
.slot.filled { border-style: solid; border-color: #cfe3d6; background: var(--ok-soft); }
.slot.missing { border-color: #ecc9a1; background: var(--gold-soft); }
/* Two states the documents panel does not have. Lapsed is red because a lender
   will not take an out-of-date consent, and a slot that still reads as filled is
   worse than an empty one. Excused is deliberately flat — it is answered, not
   satisfied, and it must never look like a document. */
.slot.lapsed { border-style: solid; border-color: #edbcb6; background: var(--bad-soft); }
.slot.excused { border-style: solid; border-color: var(--line); background: var(--paper); }
.slot-ico {
  width: 26px; height: 26px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; background: #fff; border: 1px solid var(--line);
}
.slot.filled .slot-ico { color: var(--ok); border-color: #cfe3d6; }
.slot.missing .slot-ico { color: var(--gold-deep); border-color: #ecc9a1; }
.slot.lapsed .slot-ico { color: var(--bad); border-color: #edbcb6; font-weight: 800; }
.slot.excused .slot-ico { color: var(--muted); }
/* The text column gives way to the buttons rather than pushing them out of the
   box. flex:1 with min-width:0 is the pair that makes it work — min-width alone
   permits shrinking, flex:1 makes it actually happen. */
.slot-text { flex: 1; min-width: 0; }

/* An ad-hoc document's name IS its filename, so this needs the same truncation
   the sub-line already had. title= carries the whole thing on hover. */
.slot-name {
  font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.slot-sub {
  font-size: 10.5px; color: var(--muted); margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Two blocks flush right, filled top to bottom:
       Download   Replace
       Rename     Remove
   Four actions on one line ran across the filename. grid-auto-flow: column with
   two rows means the markup order stays as it reads — download, rename, replace,
   remove — and the columns fall out of it. A slot with fewer actions simply
   fills less of the grid. */
/* Three rows, condensed:

       ✓   Privacy Consent                    Download  Rename  Replace
           Adrian Brown · valid to 15 Oct 26  Date  Remove
           PC - Adrian - 17 July 26.pdf

   The filename is the longest thing in the slot and it was sharing a line with
   the buttons — "issue was long filenames are constrained". The actions sit
   top-right over two rows; the filename runs under both columns and has the
   width of the whole slot. */
.slot { align-items: flex-start; }
.slot-body { flex: 1; min-width: 0; }
/* The head wraps rather than squeezing the name.
   "That should be able to spread all the way across to the end."

   With the panel in three columns a slot is about 250px, and an action block
   210px wide left the label 42 characters' worth of nothing — measured. Given a
   sensible basis, the text keeps the row to itself and the actions drop onto a
   line of their own when they will not both fit. */
.slot-head {
  display: flex; align-items: flex-start; gap: 10px;
  min-width: 0; flex-wrap: wrap;
}
.slot-head > .slot-text { flex: 1 1 150px; }

/* One row at the foot of the slot.

     "When files are uploaded let's make the Download Rename Replace Date
      Remove links one row at the very bottom."

   They were flush right at the top over two short columns, capped at 210px so
   the filename beneath could have the width. At the foot they have the width
   themselves, so they read left to right in one pass and the cap goes with the
   reason for it. */
.slot-actions {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 2px 14px; margin-top: 6px;
}

/* "Download is a text link, the others are grey buttons — to save space make
   them all text links." They shared a class and not an appearance: a <button>
   brings its own chrome, and only the anchor was ever styled. */
.slot-act {
  font-size: 11px; font-weight: 700; color: var(--navy); text-decoration: none;
  white-space: nowrap; font-family: inherit; line-height: 1.5;
  background: none; border: none; padding: 0; margin: 0; cursor: pointer;
}
.slot-act:hover { text-decoration: underline; }
.slot-act.is-bad { color: var(--muted); }
.slot-act.is-bad:hover { color: var(--bad); }
.slot-actions .inline-form { display: inline-flex; }

/* The filename, full width under both columns. */
.slot-file {
  margin-top: 2px; font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.slot-upload {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 12px; background: #fafbfc;
  border: 1px solid var(--line); border-radius: 10px;
}
.slot-upload input[type=file] { font-size: 12px; flex: 1 1 200px; padding: 0; border: none; }

/* a file is over this slot — "I'd rather just drop deck and it loads" */
.slot.dropping {
  border-style: solid; border-color: var(--gold-deep);
  background: var(--gold-soft); box-shadow: inset 0 0 0 1px var(--gold-deep);
}
.drop-hint { color: var(--muted); }

/* the filename itself is the way into the document */
.doc-open {
  background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; color: var(--navy); font-weight: 600; text-decoration: underline;
  text-underline-offset: 2px; text-align: left;
  /* a button is inline-block, so the sub-line's ellipsis clipped it dead rather
     than trailing off — it needs to truncate on its own account */
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; vertical-align: bottom;
}
.doc-open:hover { color: var(--gold-deep); }

/* collapsing a panel from its own heading */
.panel-toggle {
  background: none; border: none; padding: 0; cursor: pointer;
  font: inherit; color: inherit; display: inline-flex; align-items: center; gap: 6px;
}
.panel-toggle span { font-size: 10px; color: var(--muted); }

/* ---------- document pop-up ---------- */
.doc-viewer {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(16, 24, 40, .55);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.doc-viewer-box {
  background: var(--paper); border-radius: 12px; overflow: hidden;
  width: min(980px, 100%); height: min(88vh, 100%);
  display: flex; flex-direction: column; box-shadow: 0 18px 48px rgba(16, 24, 40, .28);
}
.doc-viewer-head {
  display: flex; align-items: center; gap: 14px;
  padding: 10px 14px; border-bottom: 1px solid var(--line); background: #fafbfc;
}
.doc-viewer-name {
  flex: 1 1 0; min-width: 0; font-weight: 700; font-size: 13px; color: var(--navy);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.doc-viewer-frame { flex: 1; width: 100%; border: none; background: #fff; }

/* An image is fitted to the box rather than drawn at its own size. A licence
   photographed on a phone is 4000px down the long edge, and in an iframe that
   is a top-left corner and two scrollbars.

   min-height: 0 is what lets it shrink: a flex child defaults to min-content,
   so without it the image sets the height of the box and overflows the screen
   instead of fitting inside it. */
.doc-viewer-image {
  flex: 1; min-height: 0; overflow: auto; background: #fff;
  display: flex; align-items: center; justify-content: center;
  padding: 12px; cursor: zoom-in;
}
.doc-viewer-image img {
  max-width: 100%; max-height: 100%; object-fit: contain;
}

/* and full size for reading the number off one, which is the whole reason he
   opens it */
.doc-viewer-image.is-zoomed { align-items: flex-start; justify-content: flex-start; cursor: zoom-out; }
.doc-viewer-image.is-zoomed img { max-width: none; max-height: none; }

.doc-viewer-note { padding: 32px; text-align: center; color: var(--muted); font-size: 13px; }

/* ---------- ABN lookup row ---------- */
.abn-row { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; }
input.mono { font-family: 'IBM Plex Mono', monospace; letter-spacing: .5px; }

/* ---------- Filter chips ---------- */
.filter-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 16px;
}
.fchip {
  padding: 6px 13px; border-radius: 16px; font-size: 12.5px; font-weight: 600;
  border: 1.5px solid var(--line); background: #fff; color: var(--muted);
  cursor: pointer; text-decoration: none; transition: all .15s;
}
.fchip:hover { border-color: var(--navy); color: var(--navy); }
.fchip.on { background: var(--navy); color: #fff; border-color: var(--navy); }
.fchip-count { opacity: .6; margin-left: 3px; font-variant-numeric: tabular-nums; }

/* ---------- Global search ---------- */
.search { position: relative; }
.search-results {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 18px 40px -14px rgba(13,44,59,.35);
  overflow: hidden; z-index: 40; max-height: 420px; overflow-y: auto;
}
.search-item {
  display: flex; align-items: center; gap: 11px; padding: 10px 14px;
  text-decoration: none; color: var(--ink); border-bottom: 1px solid #f0f2f3;
}
.search-item:last-of-type { border-bottom: none; }
.search-item.on { background: var(--gold-soft); }
.search-ico {
  width: 26px; height: 26px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--paper); color: var(--gold-deep); font-size: 12px;
}
.search-label { display: block; font-size: 13.5px; font-weight: 600; }
.search-sub {
  display: block; font-size: 11.5px; color: var(--muted); margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.search-type {
  margin-left: auto; font-size: 10.5px; color: var(--muted);
  text-transform: uppercase; letter-spacing: .6px; white-space: nowrap; flex-shrink: 0;
}
.search-empty { padding: 18px 16px; font-size: 13px; color: var(--muted); text-align: center; }
.search-hint { font-size: 11.5px; margin-top: 4px; }
.search-all {
  display: block; padding: 10px 14px; font-size: 12.5px; font-weight: 600;
  color: var(--navy); text-decoration: none; background: #fafbfc;
  border-top: 1px solid var(--line); text-align: center;
}
.search-all:hover { background: var(--paper); }

/* ---------- List filter ----------
   Deliberately unlike the global search box in the top bar: smaller, muted,
   funnel-marked. One searches everything; this narrows the list in front of you. */
.list-filter { position: relative; display: inline-block; }
.list-filter::before {
  content: '⌄'; position: absolute; left: 9px; top: 3px;
  font-size: 13px; color: var(--muted); pointer-events: none;
}
.list-filter input {
  width: 210px; padding: 5px 10px 5px 24px; font-size: 12px;
  border: 1px solid var(--line); border-radius: 7px; background: #fafbfc;
}
.list-filter input:focus { background: #fff; border-color: var(--navy); }
.list-filter-busy {
  position: absolute; right: 9px; top: 3px;
  color: var(--gold-deep); font-size: 15px; font-weight: 700;
  animation: filterPulse .8s ease-in-out infinite;
}
@keyframes filterPulse { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }

/* ---------- Pagination ---------- */
.pager {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 16px; border-top: 1px solid var(--line); background: #fafbfc;
}
.pager-count { font-size: 12.5px; color: var(--muted); }
.pager-count strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.pager-links { display: flex; align-items: center; gap: 4px; margin-left: auto; flex-wrap: wrap; }
.pager-btn {
  display: inline-block; min-width: 30px; text-align: center;
  padding: 5px 9px; font-size: 12.5px; font-weight: 600;
  border: 1px solid var(--line); border-radius: 7px;
  background: #fff; color: var(--navy); text-decoration: none;
  font-variant-numeric: tabular-nums;
}
.pager-btn:hover { border-color: var(--navy); background: var(--paper); }
.pager-btn.on { background: var(--navy); color: #fff; border-color: var(--navy); }
.pager-btn.disabled { color: #c2ccd1; background: #fafbfc; cursor: default; }
.pager-btn.disabled:hover { border-color: var(--line); background: #fafbfc; }
.pager-gap { padding: 0 4px; color: var(--muted); font-size: 12.5px; }

/* ---- ABN search by name ---------------------------------------------- */
.btn-link {
    background: none; border: 0; padding: 0; cursor: pointer;
    font: inherit; font-size: 12.5px; color: var(--navy);
    text-decoration: underline; text-underline-offset: 2px;
}
.btn-link:hover { color: var(--navy-deep); }

.abn-results { display: flex; flex-direction: column; gap: 6px; }

.abn-result {
    display: flex; justify-content: space-between; align-items: baseline; gap: 14px;
    width: 100%; text-align: left; cursor: pointer;
    padding: 9px 12px; background: #fff;
    border: 1px solid var(--line); border-radius: 6px;
    font: inherit; font-size: 13px;
}
.abn-result:hover { border-color: var(--navy); background: var(--paper); }

.abn-result-name { font-weight: 600; color: var(--ink); }
.abn-result-meta {
    display: flex; gap: 10px; align-items: baseline;
    font-size: 12px; color: var(--muted); white-space: nowrap;
}

.tag {
    display: inline-block; margin-left: 7px; padding: 1px 6px;
    border-radius: 3px; font-size: 10.5px; font-weight: 600;
    text-transform: uppercase; letter-spacing: .03em;
    background: var(--warn-soft); color: var(--warn);
}

/* ---- Deals ----------------------------------------------------------- */
.detail-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 14px 22px; font-size: 13.5px;
}
.detail-label {
    display: block; font-size: 11px; text-transform: uppercase;
    letter-spacing: .04em; color: var(--muted); margin-bottom: 2px;
}

/* The pipeline tiles are gone. The deal list moved to chips first and the task
   list followed on 19 August — "copy the chips instead of the big overhead boxes
   and condense the size to the same on the dashboard" — so nothing renders a
   count over a word in a box any more. */

/* the stage control on a deal record */
.stage-track { display: flex; gap: 6px; flex-wrap: wrap; }
.stage-step-form { display: contents; }
.stage-step {
    display: flex; align-items: center; gap: 7px; cursor: pointer;
    padding: 8px 12px; font: inherit; font-size: 12.5px;
    background: #fff; color: var(--muted);
    border: 1px solid var(--line); border-radius: 6px;
}
.stage-step:hover:not(:disabled) { border-color: var(--navy); color: var(--navy); }
.stage-step.done { background: var(--paper); color: var(--ink); border-color: #cfdae0; }
.stage-step.current {
    background: var(--navy); color: #fff; border-color: var(--navy); font-weight: 600;
}
.stage-step:disabled { cursor: default; }
.stage-num {
    display: inline-flex; align-items: center; justify-content: center;
    width: 17px; height: 17px; border-radius: 50%; font-size: 10px; font-weight: 700;
    background: rgba(0,0,0,.07);
}
.stage-step.current .stage-num { background: rgba(255,255,255,.22); }

/* ---- The A&L --------------------------------------------------------- */
/* The column names stay while the rows go past.
 *
 * "Can we make this sticky so as we scroll we can identify columns."
 *
 * Not position: sticky, and not for want of trying. The wrapper is
 * overflow-x:auto for the columns that run past the panel edge, which makes it
 * a scroll container on both axes — so a sticky header hangs off a box that
 * never scrolls vertically and goes nowhere. Take the wrapper away and .panel
 * clips instead, and at 1440px the table overruns it by 243px, which turns the
 * last columns from unlabelled into unreachable.
 *
 * Capping the box was the first answer and it was wrong. It only pins across
 * the difference between the table and the box — 121px of it — and then:
 * "once I go past the box to the bottom of the page and head back to the top
 * there is no longer a sticky header." Correct. There was nothing left to
 * scroll, so the page scrolled instead and took the header with it.
 *
 * So the header is copied into a bar fixed under the chrome, shown while the
 * real one is off the top and the table is still on screen. Being fixed, it
 * owes nothing to any ancestor's overflow, which is the whole reason it works
 * where sticky could not. Under .chrome at 10, so the bar above still passes
 * over it; pointer-events off, because the row underneath is the real one.
 */
.schedule-float {
  position: fixed; z-index: 9; display: none;
  overflow: hidden; pointer-events: none;
  box-shadow: 0 1px 3px rgba(16, 24, 32, .08);
}
/* the copy is measured off the real header and must not resize itself */
.schedule-float table { width: auto; table-layout: fixed; }

.schedule-scroll { overflow-x: auto; }

table.schedule { font-size: 12.5px; }
/* 8px across rather than 10. Fifteen columns, so the two pixels either side
   come to sixty across the table — most of what the asset column needed, taken
   from space that was not being read. Measured; see the [data-col] block. */
table.schedule td { padding: 8px 6px; }
table.schedule th { padding-left: 6px; padding-right: 6px; }

.row-inactive { opacity: .55; }
.row-inactive .cell-main { font-weight: 500; }
.cell-sub.stale { color: var(--warn); font-weight: 600; }

.chip {
    display: inline-block; padding: 4px 10px; border-radius: 20px;
    font-size: 12px; text-decoration: none; color: var(--navy);
    background: #fff; border: 1px solid var(--line);
}
.chip:hover { border-color: var(--navy); }
.chip.on { background: var(--navy); color: #fff; border-color: var(--navy); }

/* The two that are off unless he asks: someone else's imported tasks, and what
   he has put away himself. Quieter than the six that cut his live work by day,
   because they are not part of it — but they still read as chips, and they
   still light up when pressed. */
.chip-quiet { color: var(--muted); background: transparent; border-style: dashed; }
.chip-quiet:hover { color: var(--navy); border-style: solid; }
.chip-quiet.on { color: #fff; background: var(--muted); border-color: var(--muted); border-style: solid; }

/* bulk entry — a credit file has eight facilities on it, not one */
table.bulk-entry { font-size: 12px; }
table.bulk-entry th {
    padding: 8px 6px; font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
}
table.bulk-entry td { padding: 3px 4px; border-bottom: 1px solid var(--line); }
table.bulk-entry input, table.bulk-entry select {
    width: 100%; padding: 6px 7px; font-family: inherit; font-size: 12px;
    border: 1px solid var(--line); border-radius: 5px; background: #fff;
}
table.bulk-entry input:focus, table.bulk-entry select:focus {
    outline: none; border-color: var(--navy); background: #fffdf7;
}
table.bulk-entry .row-num {
    text-align: center; color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums;
}
.stale-cell { color: var(--warn); font-weight: 600; }

/* ---- Export column picker -------------------------------------------- */
.column-picker {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 6px 14px;
}
.column-option {
    display: flex; align-items: center; gap: 7px;
    font-size: 12.5px; cursor: pointer; padding: 3px 0;
}
.column-option input { accent-color: var(--navy); cursor: pointer; }
.column-option span { user-select: none; }

/* ---- Tasks ----------------------------------------------------------- */

.task-check { flex-shrink: 0; display: flex; }
.task-tick {
    width: 19px; height: 19px; border-radius: 5px; cursor: pointer;
    border: 1.5px solid #c3cfd5; background: #fff;
    font-size: 12px; line-height: 1; color: var(--ok);
    display: flex; align-items: center; justify-content: center;
}
/* "Some indication on each line that you push this for it to be done." The box
   was empty until it was pressed, which reads as decoration rather than as
   something to press. The tick is always there, pale enough to be an outline of
   what pressing it would do. */
.task-tick { color: #d7dee3; }
.task-tick:hover { border-color: var(--ok); color: var(--ok); background: var(--ok-soft); }
.task.done .task-tick,
.task-table tr.done .task-tick { background: var(--ok-soft); border-color: var(--ok); color: var(--ok); }

/* The dashboard, split the way he works: "his number one thing is tasks to do —
   maybe one column, and the other items in the other."

   Not an even split. The task table carries seven columns and needs the room;
   everything on the right is a short list of three fields, which reads fine
   narrow. Below 1100px it stacks, tasks first, because on a narrow screen the
   thing he opened the page for should not be under the thing he did not. */
.dash-split { display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr); gap: 16px; }
.dash-main, .dash-side { min-width: 0; }

/* The condensed width, defined once and derived rather than guessed: it is the
   fraction the dashboard gives its main column, so a list shown in both places is
   the same width in both. Change the split above and every page follows.

   "This needs the condense treatment… still full width and not the condensed
   type he prefers." Used by the task list, the compliance grid and the lender
   panel — three pages that were each picking their own number. */
.page-narrow { max-width: calc((100% - 16px) * 1.65 / 2.65); min-width: 0; }

/* The task list, which is a table and not a record.
   "Widen /tasks… as long as it doesn't go full screen — only as wide as needed."
   So: as wide as its columns need and not a pixel more. Done, date, time,
   related, priority, roll and delete total 806px between them; the rest is the
   task itself, which is the column he is actually reading. It stops at 1180
   rather than following the window out to the edge. */
.page-tasks { max-width: min(1180px, 100%); min-width: 0; }

/* The same table, two thirds of the width, in five columns rather than seven.
   Tomorrow folds under the due date and the priority sits above Delete, which
   returns their two columns to Task and Related to — the two he is actually
   reading, and the two that had nothing left. */
.dash-main .task-table th,
.dash-main .task-table td { padding-left: 8px; padding-right: 8px; }
.dash-main .related-cell { max-width: none; }
.dash-main .due-link { padding: 3px 3px; }

/* The list is wide, so its two variable columns do not need half the page each:
   a task title is a sentence, not a paragraph, and Related to holds a client and
   an application. Capped, and the rest of the width falls where the table puts
   it rather than stretching two columns across it. */
.task-table .related-cell { max-width: 360px; }

/* "The date can be on the very end. It's not really part of the task." Small and
   quiet, above the priority chip, where he looks after he has read the row. */
/* What the task is about, under what it is — the narrow shape, where a column of
   its own would take three hundred pixels a record panel has not got. Held to one
   line: a wrapped application reference turns a two-line row into four. */
.task-related-sub {
  display: block; margin-top: 2px;
  font-size: 11.5px; color: var(--muted); text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.task-related-sub:hover { color: var(--navy); text-decoration: underline; }

@media (max-width: 1100px) {
  .dash-split { grid-template-columns: minmax(0, 1fr); }
  /* where the dashboard stops splitting, these stop narrowing */
  .page-narrow { max-width: 100%; }
}

/* The task card is gone: a record's panel, the dashboard and the list all render
   the same table now — "lay out the rows to match the format just done on the
   dashboard" — so the two-line card and its column rules went with it. What the
   table still uses is below: the tick, the priority chip, the roll, the delete.

   The one thing that went with the card is the opening line of a note under each
   row. The table has always shown a `notes` tag instead, and it is one click to
   the note itself. */

.pri {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; padding: 1px 6px; border-radius: 3px;
}
.p-urgent { background: var(--bad-soft); color: var(--bad); }
.p-high { background: var(--warn-soft); color: var(--warn); }
.p-medium { background: #e8eef1; color: var(--navy); }

/* The same chip, when it is a select rather than a span.
   .pri was written for a <span> and gives 6px each side. A select draws the
   browser's own arrow inside that, so on the widest word there was nowhere for
   it to go and it sat over the last two letters — "URGE ⌄". Room on the right
   for the arrow, and the chip's own font rather than the control default. */
.pri-pick {
  width: auto; font-family: inherit; padding-right: 19px;
  border: none; cursor: pointer;
}

.task-actions { flex-shrink: 0; }
.task-actions form { display: flex; gap: 4px; }
.task-roll {
    font: inherit; font-size: 11px; cursor: pointer;
    padding: 3px 8px; border-radius: 5px;
    background: #fff; border: 1px solid var(--line); color: var(--muted);
}
.task-roll:hover { border-color: var(--navy); color: var(--navy); }

.task-add-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
/* the title takes what is left, before the fixed-width controls beside it. The
   note left this row on 19 August and has a line of its own below. */
.task-add-row input[name="title"] { flex: 1 1 240px; min-width: 0; }
/* The subject, then when and for whom, then the note under them.
   "Date, Priority and Assigned to need to be on top, not underneath Notes":
   the three facts that decide whether a task gets done are settled first, and
   the long box goes last where it can grow. */
.task-add-label {
  display: inline-block; margin: 8px 0 3px;
  font-size: 11.5px; font-weight: 700; color: var(--muted);
}
.task-add-subject {
  display: block; width: 100%;
  padding: 8px 10px; font-family: inherit; font-size: 13px;
  border: 1px solid var(--line); border-radius: 7px; background: #fff;
}
.task-add-subject:focus { outline: none; border-color: var(--navy); }

.task-add-meta {
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin-top: 10px;
}
.task-add-field { display: inline-flex; gap: 6px; align-items: center; }
.task-add-field .task-add-label { margin: 0; }

/* Related to, on the list and the dashboard only — a record's own add row
   already knows whose task it is. Wide enough for a company name, and given
   room to grow before the other fields give any up. */
.task-add-related { flex: 1 1 260px; min-width: 200px; }
.task-add-related .party-select { flex: 1 1 auto; min-width: 0; }

/* Several at once (item 39). Absent until something is ticked: a bar that is
   always there is a bar he stops seeing, and this one only ever has something
   to say once he has made a selection. */
.task-bulk-bar {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin: 0 16px 12px; padding: 9px 12px;
  border: 1px solid var(--line); border-left: 3px solid var(--gold);
  border-radius: 8px; background: var(--paper);
}
.task-bulk-bar form { display: flex; gap: 8px; align-items: center; margin: 0; }
.task-bulk-count { font-size: 12.5px; font-weight: 700; color: var(--navy); margin-right: 2px; }
.task-bulk-bar .btn-link { margin-left: auto; font-size: 12px; }

/* Chosen, not done — deliberately not the tick in the next column, which acts
   the moment it is pressed. */
.task-select { width: 15px; height: 15px; cursor: pointer; accent-color: var(--navy); }

.task-add-row input, .task-add-row select {
    padding: 8px 10px; font-family: inherit; font-size: 13px;
    border: 1px solid var(--line); border-radius: 7px; background: #fff;
}
.task-add-row input:focus, .task-add-row select:focus {
    outline: none; border-color: var(--navy);
}

/* Stage filter chips on the deals list. Distinct from the stage CONTROL on a
   deal record — one narrows a list, the other changes a deal, and confusing
   the two moved a deal by accident. */
.stage-chips { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 16px; }
.stage-chips .chip { display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; }
.chip-count {
    font-size: 11px; font-weight: 700; padding: 0 6px; border-radius: 9px;
    background: rgba(0,0,0,.07); font-variant-numeric: tabular-nums;
}
.chip.on .chip-count { background: rgba(255,255,255,.22); }

/* Task row controls. "Push to" labels what the buttons do — without it they
   read as dates rather than actions, which is exactly how they were misread. */
.task-actions { display: flex; align-items: center; gap: 6px; }
.task-delete {
    font: inherit; font-size: 15px; line-height: 1; cursor: pointer;
    padding: 2px 7px; border-radius: 5px; color: var(--muted);
    background: #fff; border: 1px solid var(--line);
}
.task-delete:hover { color: var(--bad); border-color: var(--bad); }
.tab[draggable="true"] { cursor: grab; }
.tab.dragging { opacity: .45; }

/* Where the tab will land on release. A pseudo-element rather than a box-shadow,
   because .tab.on already spends its box-shadow on the gold top bar. */
.tab { position: relative; }
.tab.drop-before::before, .tab.drop-after::after {
  content: ''; position: absolute; top: 3px; bottom: 0; width: 3px;
  background: var(--gold); border-radius: 2px;
}
.tab.drop-before::before { left: -3px; }
.tab.drop-after::after { right: -3px; }

/* The close button is a 12px glyph inside a draggable tab: it needs a real hit
   area, and its own cursor — otherwise the tab's `grab` implies dragging is all
   that will happen when you press it. */
.tab .x {
  margin-left: 1px; padding: 2px 4px; border-radius: 4px;
  line-height: 1; cursor: pointer;
}
.tab .x:hover { color: #fff; background: rgba(255,255,255,.20); }
.tab.on .x:hover { color: var(--navy-ink); background: rgba(0,0,0,.10); }

/* C21 — nav text was too small to scan */
.sidebar-nav a, .sidebar-nav .nav-soon { font-size: 14.5px; }
.section-label { font-size: 11px; }

/* The page heading now sits below the tab strip, inside the page it names,
   rather than floating above every tab in the bar. */
.page-head {
  display: flex; align-items: baseline; gap: 12px;
  padding: 18px 28px 0;
}
.page-head h1 { font-size: 19px; font-weight: 700; color: var(--navy-ink); letter-spacing: -.2px; }
.page-head .crumb { margin: 0; }

/* The results dropdown is absolutely positioned, and .panel sets overflow:hidden
   to keep tables inside its rounded corners — so the dropdown was clipped at the
   panel edge, showing a few pixels of the first result and no way to reach it.
   Panels containing a selector opt out of the clipping rather than every panel
   losing it. */
.panel.panel-overflows { overflow: visible; }

/* ---------- Party selector (F5, H6, C10) ----------
   One search box across individuals and businesses. Replaces a dropdown that
   listed every person in the database in no useful order. */
.party-select input[type=text] { width: 100%; }
.party-chip {
  display: inline-flex; align-items: center; gap: 7px; width: 100%;
  padding: 7px 10px; border: 1.5px solid var(--gold); border-radius: 9px;
  background: #fffdf5; font-size: 12.5px; font-weight: 600; color: var(--ink);
}
.party-chip-x {
  margin-left: auto; background: none; border: none; cursor: pointer;
  color: var(--muted); font-size: 15px; line-height: 1; padding: 0 2px;
  font-family: inherit;
}
.party-chip-x:hover { color: var(--bad); }

.party-results {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 4px);
  background: #fff; border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 8px 24px rgba(16,32,56,.14); overflow: hidden auto; max-height: 280px;
}
.party-group {
  padding: 7px 11px 4px; font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); background: #fafbfc;
}
.party-row {
  display: block; width: 100%; text-align: left; padding: 8px 11px;
  background: none; border: none; cursor: pointer; font-family: inherit;
  font-size: 13px; color: var(--ink);
}
.party-row.on, .party-row:hover { background: var(--gold-soft); }
.party-sub { display: block; font-size: 11.5px; color: var(--muted); margin-top: 1px; }
.party-empty { padding: 11px; font-size: 12.5px; color: var(--muted); }
/* "add a new person" — an action, not a result, so it reads differently */
.party-add { border-top: 1px solid var(--line); color: var(--navy); font-weight: 600; }
.party-add[disabled] { opacity: .6; cursor: default; }

/* a qualifier inside a label — "NAF (net amount financed)" without the shouting */
.field-note { font-weight: 400; color: var(--muted); font-size: 11.5px; }

/* Expiry on a document slot. Red is reserved for lapsed — a lender will not
   take an out-of-date consent, and a filled slot that is no longer valid is
   worse than an empty one, because it reads as done. */
.expired-date { color: var(--bad); }
.doc-expiry { margin-left: 6px; font-weight: 600; color: var(--muted); }
.doc-expiry.soon { color: var(--warn); }
.doc-expiry.expired { color: var(--bad); }
.slot-date { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.slot-date input { padding: 5px 8px; font-size: 12.5px; }

/* ---------- A&L: financial-year grouping ---------- */
/* His master sheet subtotals by FY and he reads it that way, so the CRM does
   too. Active rows only in the totals — adding paid-out ones overstates
   exposure, which is the one number that must never be wrong in front of a
   lender. */
.schedule tr.fy-head th {
  background: var(--navy-ink); color: #fff; text-align: left;
  font-size: 12px; letter-spacing: .04em; padding: 7px 10px;
}
.fy-span { font-weight: 400; color: rgba(255,255,255,.55); margin-left: 8px; }
.schedule tr.fy-total td {
  background: var(--paper); font-weight: 700; border-top: 1px solid var(--line);
}
/* The running total sits under the year's own, and has to be told apart from it
   at a glance — they carry the same four figures and only the label differs. */
/* A column that will be stripped whatever the tick beside it says — struck
   through rather than removed, so it is clear the choice was overruled and by
   what, and comes back the moment the lender tick is cleared. */
.column-option.is-struck span { text-decoration: line-through; color: var(--muted); }

/* Who is reading it, kept apart from what is on it. */
.export-options {
  display: flex; flex-direction: column; gap: 6px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line);
}
.export-options .column-option { display: inline-flex; }

.schedule tr.fy-total.is-running td {
  background: #eef2f4; border-top: 0; color: var(--navy);
}
.fy-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--muted); }

/* the override form sits inside a table cell; without this the buttons wrap */
.inline-form { display: inline; }

/* ---------- Provenance band ---------- */
.provenance {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 11px 16px; border-radius: 10px; margin-bottom: 16px;
  font-size: 12.5px; line-height: 1.5;
}
.provenance > div { margin-right: auto; min-width: 0; }
.provenance-unchecked {
  background: var(--warn-soft); border: 1px solid #f0d9b4; color: var(--ink);
}
.provenance-unchecked strong { display: block; color: var(--warn); }
.provenance-checked {
  background: var(--paper); border: 1px solid var(--line); color: var(--muted);
  padding: 8px 16px;
}
.source-chips { display: inline-flex; gap: 6px; margin-left: 10px; }

/* ---------- Company structure (party tree) ---------- */
.ptree, .ptree-children { list-style: none; margin: 0; padding: 0; }
.ptree { padding: 8px 16px 12px; }

/* Elbow connectors rather than a plain rail. This is the one change that makes
   an indented list read as a diagram: you can see where a branch ends, because
   the spine stops at the last child instead of running past it.
   Two pseudo-elements per node — a vertical spine and a horizontal arm — so
   there is nothing to lay out and any depth or shape works. */
.ptree-children { margin-left: 13px; }
.ptree-children > .ptree-node { position: relative; padding-left: 20px; }
.ptree-children > .ptree-node::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0;
  width: 1px; background: var(--line);
}
.ptree-children > .ptree-node:last-child::before { bottom: auto; height: 19px; }
.ptree-children > .ptree-node::after {
  content: ''; position: absolute; left: 0; top: 19px;
  width: 13px; height: 1px; background: var(--line);
}

/* The borrowing entity, which the tree used to start below. */
.ptree-node.is-root > .ptree-row { padding-bottom: 4px; }
.ptree-node.is-root .ptree-name { font-size: 14px; }
.ptree-node.is-root .ptree-icon { color: var(--navy); font-size: 14px; }

/* The structure said in words, above the structure drawn in lines. */
.ptree-sentence {
  margin: 12px 16px 4px; padding: 9px 12px;
  background: var(--paper); border-left: 3px solid var(--gold);
  border-radius: 0 6px 6px 0; font-size: 12.5px; line-height: 1.5; color: var(--ink);
}
/* Two children only, and no wrapping. It used to wrap, and a long legal name
   made the body demand its full content width — so the row broke *after* the
   icon and left it sitting on a line of its own above the name. flex-basis 0
   is what stops that: the body no longer asks for its content width, it takes
   what is left and wraps its own text. */
.ptree-row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 7px 0; min-width: 0;
}
.ptree-icon {
  color: var(--gold-deep); font-size: 12px; width: 14px; flex: 0 0 14px;
  line-height: 1.5;
}
.ptree-body { display: flex; flex-direction: column; flex: 1 1 0; min-width: 0; }

/* The controls, on their own line under the name. */
.ptree-actions {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 5px;
}
.ptree-actions:empty { display: none; }
/* a legal name can be sixty characters and has to wrap rather than push the row */
.ptree-name {
  font-size: 13px; font-weight: 600; color: var(--ink); text-decoration: none;
  overflow-wrap: anywhere; line-height: 1.4;
}
.ptree-name:hover { color: var(--navy); text-decoration: underline; }
.ptree-sub { font-size: 11.5px; color: var(--muted); }
/* The role is what the eye goes to on a structure — it was a grey pill losing to
   the entity type beside it. */
.ptree-row .pill { font-weight: 700; letter-spacing: .03em; }

/* A capacity and the X that removes it, as one object. They used to be a pill
   and, further along the row, an anonymous X — with two roles on one person
   there was no way to tell which X did what. */
.ptree-role {
  display: inline-flex; align-items: center; gap: 1px;
  padding: 2px 3px 2px 8px; border-radius: 999px;
  background: var(--paper); border: 1px solid var(--line);
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.ptree-role form { display: inline-flex; }
.ptree-role button {
  background: none; border: none; cursor: pointer; color: var(--muted);
  font-size: 14px; line-height: 1; padding: 0 4px; border-radius: 999px;
}
.ptree-role:hover { border-color: var(--gold); color: var(--ink); }
.ptree-role button:hover { color: var(--bad); }

/* Removes the party, not a capacity — set apart from the role chips so the two
   Xs cannot be confused. Pushed to the end of the controls line, away from the
   role chips' own Xs. */
.ptree-remove { display: inline-flex; margin-left: auto; padding-left: 8px; }
.ptree-remove button {
  background: none; border: none; cursor: pointer; color: #c2c8d0;
  font-size: 16px; line-height: 1; padding: 0 3px;
}
.ptree-remove button:hover { color: var(--bad); }

.ptree-inline { display: inline-flex; }

/* the same chips in a table cell — a person's list of companies */
.role-chips { text-align: right; white-space: normal; }
.role-chips .ptree-role { margin: 2px 0 2px 6px; }

/* Tomorrow and Delete are set apart by the table itself now — Tomorrow under the
   due date it rolls, Delete in the last column — so the gap this held open is no
   longer needed. Two live controls a few pixels apart is how a task gets deleted
   instead of rolled, and three columns is further than any padding. */

/* the record's own form, opened inside its panel rather than on its own page */
.panel-edit { padding: 12px 14px 0; }
.panel-edit-foot { display: flex; gap: 10px; padding: 4px 0 14px; }
.ptree-quiet, .ptree-addrole {
  background: none; border: none; cursor: pointer; padding: 2px 4px;
  font-size: 11px; font-weight: 600; color: var(--muted);
  font-family: inherit; border-radius: 4px;
}
.ptree-quiet:hover, .ptree-addrole:hover { color: var(--navy); background: var(--paper); }
.ptree-addrole { color: var(--gold-deep); }

/* Opens under the row it belongs to, full width, like the document slots. */
.ptree-addrow {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0 0 8px 34px; padding: 8px 10px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 6px;
}
.ptree-addrow select { padding: 5px 8px; font-size: 12.5px; }

/* ---------- Trading history: one business under another ----------
   Newest at the top, the way he says it: "he's gone from sole trader into a
   company, and then that company can then convert into a trust." */
.chain { list-style: none; margin: 0 0 16px; padding: 0; }
.chain li { position: relative; padding: 0 0 12px 20px; }
.chain li::before {
  content: ''; position: absolute; left: 4px; top: 5px;
  width: 7px; height: 7px; border-radius: 50%;
  background: #fff; border: 2px solid var(--line);
}
.chain li.is-current::before { border-color: var(--gold); background: var(--gold); }
/* the run between them, stopping at the last */
.chain li:not(:last-child)::after {
  content: ''; position: absolute; left: 7px; top: 14px; bottom: 0;
  width: 1px; background: var(--line);
}
.chain-name { display: block; font-size: 13px; font-weight: 600; color: var(--ink); }
.chain-name a { color: var(--ink); text-decoration: none; }
.chain-name a:hover { color: var(--navy); text-decoration: underline; }
.chain-sub { display: block; font-size: 11.5px; color: var(--muted); }

/* Meant to be read and copied, not typed into. Sized for a third of the page,
   because that is where it sits — under the entity's own details. The longest
   line it has to hold is a legal name, and 11px mono clears one comfortably. */
.note-block {
  width: 100%; resize: vertical; font-size: 11px; line-height: 1.55;
  background: var(--paper); color: var(--ink); border: 1px solid var(--line);
  padding: 8px 10px;
}

/* ---------- Setting how warm a client is ---------- */
.status-set {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 9px 16px; border-bottom: 1px solid var(--line); background: #fafbfc;
}
.status-set .meta { margin-right: auto; }
.status-set button { font-family: inherit; cursor: pointer; }

/* ---------- The foot of a list ---------- */
.list-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
}
.page-size { display: inline-flex; align-items: center; gap: 5px; margin-left: auto; }
.page-size .chip { padding: 3px 10px; font-size: 11.5px; }

/* ---------- Existing client or someone new ----------
   Two words rather than a dropdown: it is the first decision on the form and it
   only ever has two answers. */
.mode-switch { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.mode-switch label {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  padding: 7px 13px; border: 1px solid var(--line); border-radius: 999px;
  font-size: 12.5px; font-weight: 600; color: var(--muted); background: #fff;
}
.mode-switch label.on { border-color: var(--gold); background: #fffdf6; color: var(--ink); }
.mode-switch input { width: auto; margin: 0; cursor: pointer; }

/* A fieldset only for the sake of :disabled — it must not look like one. */
.bare-fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }

/* ---------- Loan details: a figure and its percentage, side by side ----------
   "Deposits, sometimes I get to put 10%, 20%, and if I type in 10% and it
   automatically calculates it for me, fantastic." Two boxes, either of which
   fills the other, reading as one field. */
.pair-inputs { display: flex; gap: 6px; }
.pair-inputs > * { flex: 1 1 0; min-width: 0; }

/* Under the pair, not in it. As a third child it fought .pair-inputs for width
   and won, covering the two money fields. */
.balloon-basis { margin-top: 6px; font-size: 12px; padding: 5px 8px; }

/* the one control the trading history panel has left */
/* ---------- address history ---------- */
.addr-list { padding: 8px 14px 12px; display: grid; gap: 6px; }
.addr {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 9px; background: #fff;
}
.addr.is-current { border-color: #cfe3d6; background: var(--ok-soft); }
.addr-body { flex: 1 1 0; min-width: 0; }
.addr-where { font-weight: 600; font-size: 13px; color: var(--ink); }
.addr-when { font-size: 11px; color: var(--muted); margin-top: 1px; }
.addr-when .short, .panel-head .short { color: var(--bad); font-weight: 600; }
.addr-remove { flex: 0 0 auto; }
.addr-remove button {
  background: none; border: none; cursor: pointer; color: #c2c8d0;
  font-size: 16px; line-height: 1; padding: 0 3px;
}
.addr-remove button:hover { color: var(--bad); }
.addr-add { padding: 10px 14px 14px; border-top: 1px solid var(--line); background: #fafbfc; }

/* "The dates say this" reads differently from "I said this" — outlined rather
   than filled, so the row always shows where a client stands without claiming
   somebody chose it. */
.chip.on.is-derived {
  background: #fff; color: var(--navy); border-color: var(--navy);
  border-style: dashed;
}

/* Whoever is already on the record, offered as one press against a question
   that would otherwise mean typing their name again. */
.needs-already { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.needs-pick {
  font: inherit; font-size: 11.5px; font-weight: 600; cursor: pointer;
  padding: 3px 9px; border-radius: 999px;
  background: #fff; border: 1px solid var(--line); color: var(--navy);
}
.needs-pick:hover { border-color: var(--navy); background: var(--navy); color: #fff; }

/* Everything outside the named slots — drop as many as you like */
.drop-many {
  border: 1px dashed var(--line); border-radius: 10px; padding: 8px;
  transition: border-color .15s, background .15s;
}
.drop-many.dropping { border-color: var(--gold-deep); background: var(--gold-soft); }
.drop-many-hint { font-size: 10.5px; color: var(--muted); text-align: center; padding: 5px 2px 1px; }

/* ---------- the notepad ---------- */

/* "It's not being constrained inside the container." A pasted URL or a long
   unbroken string ran outside the panel and took the text with it. */
.note-body { font-size: 13.5px; line-height: 1.55; overflow-wrap: anywhere; }
.note-body > div { min-height: 1.55em; }

/* "Timestamps to be bold and blue." Picked out wherever a note is read, and
   the same in the editor as on the page — one class, one rule. */
.note-stamp { font-weight: 700; color: var(--navy); margin-top: 4px; }
.note-body > .note-stamp:first-child,
.note-input > .note-stamp:first-child { margin-top: 0; }

/* Lists inside a note. A contenteditable produces them and nothing else on the
   page styles a bare ul. */
.note-body ul, .note-body ol, .note-input ul, .note-input ol {
  margin: 4px 0 4px 20px; padding: 0;
}
.note-body li, .note-input li { margin: 1px 0; }

/* "All note boxes to be pretty text — ie on top you can select bold, italics
   etc." A toolbar over a contenteditable, with no library behind it: the front
   end has no build step, and a CDN would be an external dependency on a page
   holding client data. */
.note-tools {
  display: flex; align-items: center; gap: 2px; flex-wrap: wrap;
  padding: 5px 6px; margin-bottom: -1px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 8px 8px 0 0;
}
.note-tools button {
  min-width: 28px; height: 26px; padding: 0 8px;
  background: none; border: none; border-radius: 5px; cursor: pointer;
  font-family: inherit; font-size: 12.5px; color: var(--ink); line-height: 1;
}
.note-tools button:hover { background: #fff; box-shadow: inset 0 0 0 1px var(--line); }

/* "Move Save and Cancel to the top right, in the same row as bold, italic,
   underline." This is what pushes them there — everything before it sits left,
   everything after it sits right. The buttons keep their own styling, so they
   still read as the things that end the edit rather than as more formatting. */
.note-tools-gap { flex: 1 1 auto; }
.note-tools .btn { height: 26px; padding: 0 12px; }
.note-tools button.is-stamp { font-weight: 700; color: var(--navy); }
.note-tools-sep { width: 1px; height: 16px; background: var(--line); margin: 0 4px; }

/* The box itself. A contenteditable has no rows attribute and no placeholder,
   so both are done here. */
.note-input {
  width: 100%; font-size: 13.5px; line-height: 1.55;
  min-height: 220px; max-width: 100%; overflow-wrap: anywhere;
  padding: 10px 12px; background: #fff;
  border: 1px solid var(--line); border-radius: 0 0 8px 8px;
  overflow-y: auto; resize: vertical;
}
.note-input:focus { outline: none; border-color: var(--navy); }
/* An empty notepad says nothing. It carried a data-placeholder suggesting what
   to write — "what needs doing, what was said, what is waiting on whom" — and he
   does not want to be prompted: "he hates suggestive text anywhere." */

/* Copy to clipboard. Quiet until the row is hovered, so a page of them does not
   read as a page of buttons — he wants the value, and the control second. */
.copy-btn {
  background: none; border: none; cursor: pointer; padding: 0 4px;
  font-size: 12px; line-height: 1; color: #c2c8d0;
  vertical-align: baseline; transition: color .15s;
}
.dl-row:hover .copy-btn, .copy-btn:focus-visible { color: var(--navy); }
.copy-btn:hover { color: var(--gold-deep); }
.copy-btn.is-done { color: var(--ok); }

.chain-set { padding: 10px 16px; border-top: 1px solid var(--line); background: #fafbfc; }
.chain-set form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* A textarea is for writing in. The squeeze took padding off every field, and
   on a four-row box that left something you could not read a paragraph in. */
textarea { min-height: 84px; line-height: 1.5; }

.unit-input { position: relative; display: flex; align-items: center; }
.unit-input input { width: 100%; }
.unit-input .unit {
  position: absolute; font-size: 11px; font-weight: 700; color: var(--muted);
  pointer-events: none; letter-spacing: .02em;
}
/* A box can carry both — "$ 2,000.00 ex" — so which end a symbol sits at is said
   on the symbol, and the room made for it is said on the wrapper. Selecting
   :first-child for the leading one broke as soon as a box had two. */
.unit-input .unit-lead { left: 9px; }
.unit-input .unit-trail { right: 9px; }
.unit-input.leading input { padding-left: 19px; }
.unit-input.trailing input { padding-right: 30px; }

/* The end figures, set apart from what he types to get them. */
.totals {
  margin-top: 4px; padding: 12px 14px 4px;
  background: var(--paper); border: 1px solid var(--line);
  border-left: 3px solid var(--gold); border-radius: 0 6px 6px 0;
}
.totals-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 10px; font-size: 12.5px;
}
.totals-override {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--muted); cursor: pointer; font-weight: 600;
}
.totals-override input { width: auto; margin: 0; cursor: pointer; }

/* Calculated rather than typed — readable, and clearly not a box awaiting input. */
input.is-derived {
  background: #f4f6f9; color: var(--ink); font-weight: 700;
  border-style: dashed; cursor: default;
}

/* ---------- What the entity type still asks for ---------- */
.needs { border-top: 1px solid var(--line); padding: 10px 16px 4px; }
.needs-head {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 12px; margin-bottom: 8px; color: var(--ink);
}
.needs-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 9px 11px; margin-bottom: 8px; border-radius: 6px;
  background: var(--paper); border: 1px solid var(--line); border-left-width: 3px;
}
/* the shape is wrong without it, so it carries the weight */
.needs-row.is-required { border-left-color: var(--gold); background: #fffdf7; }
.needs-row.is-suggested { border-left-color: var(--line); }
.needs-ask { flex: 1 1 100%; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.needs-of { font-weight: 600; color: var(--ink); }
.needs-q { font-weight: 600; color: var(--ink); }
.needs-row .party-select { flex: 1 1 220px; }

/* ---------- Address type-ahead (G-NAF) ---------- */
.address-select { position: relative; }
.address-select .address-search { width: 100%; }
.address-select .party-results { left: 0; right: 0; }

/* ---------- Restored draft (the new-business form) ---------- */
.draft-notice {
  margin-bottom: 14px; padding: 9px 13px; border: 1px solid var(--line);
  border-left: 3px solid var(--gold); border-radius: 4px; background: #fffdf6;
  font-size: 12.5px; color: var(--ink);
}
.link-btn {
  background: none; border: none; padding: 0; margin-left: 6px;
  font-family: inherit; font-size: inherit; color: var(--navy);
  text-decoration: underline; cursor: pointer;
}

/* ---------- Task table (E8) ----------
   The list was a stack of cards: no columns to sort, nothing lining up, and
   notes taking vertical space on every row whether or not anyone wanted them. */
.task-table { width: 100%; border-collapse: collapse; }
.task-table thead th {
  text-align: left; padding: 9px 10px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
  background: #fafbfc; border-bottom: 1px solid var(--line); white-space: nowrap;
}

/* The columns that hold one short fact each: a date, a time, and the two
   controls. Snug, and never wrapped — "date and time should be snug, task can
   lose a little, roll and delete should be snug also, not spaced out."

   The width they were given was being ignored: on auto layout a table set to
   100% shares its spare width across every column, so a panel wider than the
   content pushed all six apart evenly. Task carries width:100% now, which takes
   the slack, and these hold what they asked for. */
.task-table .due-cell,
.task-table .task-roll-cell,
.task-table .task-delete-cell,
.task-table .task-check-cell,
.task-table thead th:first-child { padding-left: 6px; padding-right: 6px; }

/* Date beside time, and roll beside delete, are pairs — two halves of one fact
   and two halves of one decision. The gap inside a pair is smaller than the gap
   between them and the task: "Date and Time, Roll and Delete can be closer." */
.task-table .due-cell + .due-cell,
.task-table .task-roll-cell + .task-delete-cell { padding-left: 2px; }
.task-table .due-cell:first-of-type { padding-right: 2px; }
.task-table .due-cell,
.task-table .task-roll-cell,
.task-table .task-delete-cell { white-space: nowrap; }

.task-table td {
  padding: 10px 10px; border-bottom: 1px solid var(--line);
  font-size: 13px; vertical-align: middle;
}

/* ---------------------------------------------------------------------------
   The list, packed tighter.

     "Too much vertical space — he wants more tasks on a page."

   Measured before touching it: a row was 53px, of which 20 was padding, and
   348px of the screen went on everything above the first row. Ten rows on a
   900px window.

   This is the list only. The panels on a record show four or five tasks beside
   a notepad and are not the thing he is scrolling; the dashboard has its own
   sizing already. Only the page he works down all day is squeezed.

   It costs air, and he knows: "I know it will impact appearance but his call."
   What it does not cost is anything he reads — no column, no line, no tag has
   been taken away to make the room.
   --------------------------------------------------------------------------- */
.page-tasks .task-table td { padding: 4px 10px; }
.page-tasks .task-table thead th { padding: 5px 10px; }

/* The two lines in the Task and Related to cells sat on 1.45; at 13px that is
   five pixels of leading a row, twice over. */
.page-tasks .task-table .cell-main,
.page-tasks .task-table .cell-sub { line-height: 1.25; }

/* The controls set the floor once the padding is gone: a 26px button in a 22px
   row is what stops it getting shorter. */
.page-tasks .task-table .due-link,
.page-tasks .task-table .task-roll-cell .btn,
.page-tasks .task-table .task-delete { padding-top: 2px; padding-bottom: 2px; }
.page-tasks .task-table .task-tick { width: 18px; height: 18px; }

/* Tried and reverted: pulling the line-height in to 1.2 and shrinking the date
   link and the roll button. Measured before and after and the row did not move
   — once the padding is gone the height is set by the rows that carry two lines
   under the title, not by leading or by any control. Left out rather than kept,
   because it changed how the row looked and bought nothing.
   The next thing that would actually shorten it is that second line, and that
   is content rather than air. */

/* And the room above the first row: the chips, the add row and the heading were
   each carrying their own margin into a page that is a list. */
.page-tasks .panel-head { padding: 7px 16px; }
.page-tasks .panel-body { padding: 7px 16px; }
.page-tasks .filter-bar { margin-bottom: 8px !important; }
.task-table tbody tr.task-row:hover { background: #fbfcfd; }
.task-table tr.done .cell-main { text-decoration: line-through; color: var(--muted); }

/* Saved, said on the row.

   "When the task updates there is the green bar on top to say it updated. When
   it closes it snaps the row higher — if you're editing rows it can confuse."

   The banner is inserted above the list, so every row drops by its height and
   climbs back six seconds later while he is reading one. This costs no height
   and moves nothing: the row lights and fades where it already is. It stays
   inside the cells so the row's own hover, overdue and done styling is
   untouched a second later. */
.task-table tbody > tr.task-row > td { transition: background-color 900ms ease; }
.task-table tbody.is-saved > tr.task-row > td {
  background-color: rgba(240, 180, 95, 0.28);
  transition: none;
}

.th-sort { color: inherit; text-decoration: none; }
.th-sort:hover { color: var(--navy); }
.th-sort.on { color: var(--navy); }

/* E6 — due today must not read as another grey date */
.due-today { color: var(--navy); font-weight: 700; }
.due-overdue { color: var(--bad); font-weight: 700; }

/* The title is the control. It linked to the task's own page, which opened a
   tab — "clicking on the task opens it in a new tab, which we don't want" — so
   pressing it now opens the row where it stands. Styled as the title it is, not
   as a button. */
.task-open {
  background: none; border: none; cursor: pointer; font: inherit;
  padding: 0; margin: 0; text-align: left;
  display: inline-flex; gap: 5px; align-items: baseline;
}
.task-caret { font-size: 10px; color: var(--muted); }
.task-open:hover .cell-main { color: var(--navy); text-decoration: underline; }

/* "Make related to wider so it doesn't wrap." Both lines hold their line and
   the full text is on hover — a wrapped asset description turned a one-line
   fact into three, and pushed every other cell in the row down with it. */
.related-cell { max-width: 320px; }
.related-cell .cell-main, .related-cell .cell-sub {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.task-expand {
  background: none; border: none; cursor: pointer; font-family: inherit;
  font-size: 11.5px; color: var(--muted); padding: 2px 4px; margin-left: 6px;
  display: inline-flex; gap: 4px; align-items: center;
}
.task-expand:hover { color: var(--navy); }

.task-detail > td { background: #fafbfc; padding: 14px 12px 16px; }
.task-detail-form label { font-size: 11.5px; }

/* ---------- Deals list, tranche 4 ---------- */
/* B2 — set the stage without opening the deal. Deliberately plain: it is a
   control in a table cell, not a chip. */
.stage-inline {
  width: 100%; padding: 5px 7px; font-size: 12px; font-family: inherit;
  border: 1px solid var(--line); border-radius: 7px; background: #fff;
  color: var(--ink); cursor: pointer;
}
.stage-inline:hover { border-color: var(--navy); }

/* D4 — reachable, but visibly not part of the working pipeline */
.chip-quiet { opacity: .72; border-style: dashed; }
.chip-quiet.on { opacity: 1; border-style: solid; }

/* C20 — the stage panel says what it is before you click anything */
/* One row: the track, a divider, then the two stages that are not steps. The
   heading and "Currently at X" said what the highlighted step already says. */
/* "Still too much above and below." It is a strip he glances at on the way past,
   not a panel he reads. */
.stage-bar { margin-bottom: 12px; }
.stage-bar .panel-body { padding: 2px 8px; }
.stage-bar .stage-track { padding: 0; }
.stage-bar .stage-step { padding: 4px 9px; font-size: 11.5px; }
.stage-bar .stage-num { font-size: 9.5px; }
.stage-sep {
  width: 1px; align-self: stretch; margin: 2px 6px;
  background: var(--line); flex: 0 0 1px;
}
.stage-step-out { color: var(--muted); }
.stage-step-out.current { color: var(--bad); font-weight: 700; }

.stage-now {
  font-size: 13px; color: var(--muted); margin-bottom: 12px;
}
.stage-now strong { color: var(--navy-ink); }
.stage-out {
  margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--line);
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
}
.stage-out .meta { margin-right: 2px; }


/* Column headings never wrap. Appending a sort arrow makes a heading one word
   longer, which tipped Lender, Contract no., Financed and Next task onto two
   lines — and a two-line heading reads as though the arrow belongs to something
   else. The tables already scroll inside their own container, so the width this
   costs is paid there rather than by the page. */
thead th, .task-table thead th { white-space: nowrap; }
.th-sort { white-space: nowrap; }

/* ---------- Deals list column sizing ---------- */
/* The MF number is one token — wrapping it makes the thing you quote on the
   phone unreadable. */
.col-ref, th.col-ref { white-space: nowrap; }

/* The stage select was sized by the column, so "Application submitted" and
   "Settlement conditions" were cut off. Give it the room its longest label
   needs rather than letting the table decide. */
.col-stage, th.col-stage { white-space: nowrap; }
.col-stage .stage-inline { width: 100%; min-width: 172px; }

/* Out-of-pipeline chips sit on the same row, after a divider, so the row does
   not cost two lines to say the same thing. */
.chip-divider {
  display: inline-block; width: 1px; align-self: stretch;
  min-height: 20px; background: var(--line); margin: 0 4px;
}

/* Undo, offered inline in the confirmation. A one-click action that cannot be
   reversed in one click is a trap, and a tick box in a table looks like row
   selection whatever the tooltip says. */
.alert-undo {
  background: none; border: none; cursor: pointer; font-family: inherit;
  font-size: inherit; font-weight: 700; color: inherit;
  text-decoration: underline; padding: 0; margin-left: 10px;
}
.alert-undo:hover { opacity: .75; }

/* The tick used to name itself — "Mark done" under the box. "Remove the word
   marked done, not necessary, make the box smaller, create space." The tooltip
   says what it does; the row gets the width back. */
.task-check { display: flex; align-items: center; justify-content: center; }

/* The task CARD — dashboard, and the panel on a record — still has the two
   native inputs. Its layout is a flex row rather than a table, so nothing wrapped
   there and there was no reason to change it with the list. If the picker is
   wanted there too, this block is what it replaces.

   `input.` not `.` — the shared rule is input[type=date] at (0,1,1). A bare
   class is (0,1,0) and loses, so these came out full width at 14px. */
.task-due { display: inline-flex; }
input.task-due-date, input.task-due-time {
  width: auto; padding: 3px 6px; font-size: 11.5px; font-family: inherit;
  border: 1px solid transparent; border-radius: 6px; background: transparent;
  color: var(--ink); cursor: pointer; line-height: 1.3;
}
input.task-due-time { color: var(--muted); margin-left: 2px; }
input.task-due-date:hover, input.task-due-time:hover {
  border-color: var(--line); background: #fff;
}
.due-overdue input.task-due-date, .due-overdue input.task-due-time { color: var(--bad); font-weight: 600; }
.due-today input.task-due-date, .due-today input.task-due-time { color: var(--navy); font-weight: 600; }

/* The due date is one line and one link. Two native inputs side by side wrapped
   in the column, so a fact that reads as one line took two — and each opened
   whatever picker the browser happened to have. */
.due-pick { position: relative; }
.due-link {
  font: inherit; font-size: 12px; font-variant-numeric: tabular-nums;
  padding: 3px 6px; border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: var(--navy); cursor: pointer;
  text-decoration: underline; text-decoration-style: dotted;
  text-underline-offset: 3px; white-space: nowrap;
}
.due-link:hover { border-color: var(--line); background: #fff; text-decoration-style: solid; }
/* today and overdue still have to be unmistakable, and the cell colour has to
   reach into the link to say so */
.due-overdue .due-link { color: var(--bad); font-weight: 700; }
.due-today .due-link { color: var(--navy); font-weight: 700; }

/* Fixed, not absolute: the table sits in an overflow-x:auto wrapper so the page
   never scrolls sideways, and that wrapper clips anything absolutely positioned
   inside it — the calendar would have been cut off at the cell edge. The cost is
   measuring the link on open, which duePicker() does. */
.due-pop {
  position: fixed; z-index: 60; width: 384px;
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 12px 32px rgba(16, 34, 48, .18);
}
.due-pop-body { display: flex; }
.due-cal { flex: 1 1 auto; padding: 10px 10px 8px; border-right: 1px solid var(--line); }
.due-cal-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 12.5px; font-weight: 700; color: var(--ink); padding: 0 2px 8px;
}
.due-cal-head button {
  font: inherit; font-size: 15px; line-height: 1; cursor: pointer;
  border: 1px solid var(--line); background: #fff; color: var(--muted);
  border-radius: 5px; padding: 1px 8px;
}
.due-cal-head button:hover { color: var(--navy); border-color: var(--navy); }
.due-cal-dow, .due-cal-week { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.due-cal-dow span {
  text-align: center; font-size: 10px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em; padding-bottom: 3px;
}
.due-day {
  font: inherit; font-size: 11.5px; font-variant-numeric: tabular-nums;
  padding: 4px 0; cursor: pointer; border-radius: 5px;
  border: 1px solid transparent; background: transparent; color: var(--ink);
}
.due-day:hover { background: var(--paper); }
.due-day.outside { color: #c3cfd5; }
.due-day.today { border-color: var(--line); font-weight: 700; }
.due-day.on { background: var(--navy); border-color: var(--navy); color: #fff; font-weight: 700; }

/* "A scrollable list of 15 minute slots." Ninety-six of them, so the list opens
   at the one already chosen rather than at midnight. */
.due-slots {
  flex: 0 0 96px; max-height: 252px; overflow-y: auto;
  display: flex; flex-direction: column; padding: 6px;
}
.due-slot {
  font: inherit; font-size: 11.5px; font-variant-numeric: tabular-nums;
  text-align: center; padding: 4px 0; cursor: pointer; border-radius: 5px;
  border: 1px solid transparent; background: transparent; color: var(--ink);
}
.due-slot:hover { background: var(--paper); }
.due-slot.on { background: var(--navy); border-color: var(--navy); color: #fff; font-weight: 700; }

.due-pop-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border-top: 1px solid var(--line); background: #fafbfc;
  border-radius: 0 0 9px 9px;
}
.due-chosen {
  flex: 1 1 auto; font-size: 12px; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* A facility opened in its own row. "Editing a facility opens a new pane — it
   should be a dropdown in the row."

   The cell spans the table, so the form has to be told not to grow it: the
   schedule sits in an overflow-x:auto wrapper and a form wider than the columns
   would set the scroll width for every row. */
.schedule tr.facility-edit > td {
  background: var(--paper); padding: 12px 14px; border-bottom: 2px solid var(--line);
}
.schedule tr.facility-edit .panel { margin-bottom: 10px; box-shadow: none; }
.schedule tr.facility-edit .panel:last-of-type { margin-bottom: 12px; }
.edit-toggle {
  background: none; border: none; padding: 0; font: inherit; cursor: pointer;
}

/* Roll and Delete are columns of their own, under headings that say so. The gap
   that used to keep them apart is now the gap between two cells. */
.task-roll-cell form, .task-delete-cell form { display: inline-flex; }

/* One roll button now, not three controls. The date picker above covers
   everything that is not tomorrow. */
.task-actions { flex-wrap: nowrap; white-space: nowrap; }

/* Delete said "×", which is a guess dressed as a control. It says Delete, in the
   colour of the thing it does, and still confirms — this one cannot be undone. */
.task-delete {
  font-size: 11px; padding: 3px 9px; border-radius: 5px;
  color: var(--bad); border-color: #e8c9c6; margin-left: 10px;
}
.task-delete:hover { background: var(--bad-soft); border-color: var(--bad); }

/* "Add a lender →" on the deal form. It was field-hint sized, which made the
   one thing you are meant to click smaller than the label above it, and it sat
   hard against the next field. */
.add-inline {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: 10px 0 18px;
}
.add-inline-link {
  font-size: 13.5px; font-weight: 700; color: var(--navy); text-decoration: none;
}
.add-inline-link:hover { color: var(--navy-deep); text-decoration: underline; }
.add-inline-note { font-size: 12px; color: var(--muted); }

/* A deal tab carries its full name — reference, asset and business — which is
   right on the page and too wide for a tab. Cap it and truncate; the whole name
   is on hover. */
.tab { max-width: 280px; }
.tab .tlabel {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

/* ---------------------------------------------------------------------------
   The ABN lookup disagreeing with the record it was run on.

   Held back rather than applied, both sides shown, and neither button is the
   default — the one that overwrites is the one that looks like it does.
   --------------------------------------------------------------------------- */
.abn-conflict {
  margin-top: 14px;
  border: 1.5px solid var(--warn);
  border-radius: 10px;
  background: #fffaf2;
  padding: 14px 16px;
}
.abn-conflict-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.abn-conflict-head strong { color: var(--warn); font-size: 14px; }
.abn-conflict-stake {
  margin: 6px 0 0;
  font-size: 12.5px;
  color: var(--bad);
}
.abn-conflict-table {
  width: 100%;
  border-collapse: collapse;
  margin: 12px 0 4px;
  font-size: 13px;
}
.abn-conflict-table th,
.abn-conflict-table td {
  text-align: left;
  padding: 6px 10px 6px 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.abn-conflict-table thead th {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted);
  font-weight: 600;
}
.abn-conflict-table tbody th {
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
  width: 1%;
}
.abn-conflict-table td.to { color: var(--warn); font-weight: 600; }
.abn-conflict-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
}
.btn-replace { background: var(--bad); color: #fff; }
.btn-replace:hover { background: #932c25; }
.abn-conflict-note {
  margin: 10px 0 0;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
}

/* ---------------------------------------------------------------------------
   A6 — the structure row reads as something you can open.

   It was a link the whole time, in plain ink with no underline, so nothing said
   so: "I can't select this. That's been a problem… for the last week." The
   subtitle now sits inside the anchor as well, which roughly doubles the target.
   --------------------------------------------------------------------------- */
.ptree-open {
  display: flex; flex-direction: column; min-width: 0;
  text-decoration: none; border-radius: 5px;
}
.ptree-open .ptree-name { color: var(--navy); }
.ptree-open:hover .ptree-name { text-decoration: underline; }
.ptree-chev { color: var(--muted); font-weight: 400; margin-left: 5px; }
.ptree-open:hover .ptree-chev { color: var(--navy); }

/* ---------------------------------------------------------------------------
   A8 — the trustee under its trust on a person's page.

   "This company should be a part of the trust… I don't want to see the company
   structure, I just want to know that it's affiliated to it. It's a snapshot."
   --------------------------------------------------------------------------- */
.affil-child > td:first-child { padding-left: 30px; position: relative; }
.affil-child > td:first-child::before {
  content: ''; position: absolute; left: 12px; top: 0; bottom: 50%;
  width: 1px; background: var(--line);
}
.affil-child > td:first-child::after {
  content: ''; position: absolute; left: 12px; top: 50%;
  width: 11px; height: 1px; background: var(--line);
}
.affil-rel {
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--gold-deep); margin-bottom: 2px;
}

/* ---------------------------------------------------------------------------
   C1/C2/C3 — the A&L, read as a statement and edited in place.

   "This grid is permanently editable and ugly." A row of text with Edit and
   Delete at the end; Edit turns that row into fields without moving anything.
   --------------------------------------------------------------------------- */
.al-section { border-top: 1px solid var(--line); }
.al-section:first-of-type { border-top: none; }

.al-section-head {
  display: flex; align-items: baseline; gap: 10px;
  padding: 11px 16px 7px;
}
.al-section-head strong {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
}
/* The total, with what it costs a month under it rather than beside it: one is
   what he owes and the other is what servicing it takes, and side by side they
   read as two halves of one figure. */
.al-total {
  margin-left: auto; text-align: right;
  font-size: 14px; font-weight: 700; color: var(--ink);
}
.al-sub { display: block; font-size: 11.5px; font-weight: 500; color: var(--muted); }

/* "Make the net bold." */
.al-net { color: var(--ink); font-weight: 700; }

/* A facility a settled deal wrote, in the list with everything else. It reads
   the same; what marks it is that its row points at the deal rather than
   offering Edit and Delete, because the deal is where it is corrected. */
.al-financed td { background: #fcfdfd; }

/* "It pisses me off when the thing is spread out all across the page… it's just
   annoying to get property all the way to the other end to see what its value
   is. I've got to catch my line across."

   Four columns do not need a screen. Assets take half of it, liabilities
   three-quarters — they carry eight columns and cannot go further — and the gap
   between columns comes in with them, which is what he was actually reading
   across. Capped as well as proportioned, so a wide monitor does not put the
   value back where it was. */
.al-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
/* Widened 28 August: "the whole Asset panel can also widen."
   620px was set when the row was three short columns of reading text. It now
   has to hold a type dropdown wide enough for "Business or company value" and
   a description box worth typing into, and it was stopping halfway across the
   page with the liabilities table below it running twice as far. */
.al-assets { max-width: min(72%, 920px); }

/* "It pisses me off when the thing is spread out all across the page… it's just
   annoying to get property all the way to the other end to see what its value
   is." That is a person's declared A&L — eight columns, four of them one word
   — and it stays reined in. */
/* Widened again 28 August: "panel can be larger." The row has to hold a type
   dropdown 248px wide and a frequency one that fits "Fortnightly", and at
   1080px what was left over came out of the description. */
.al-liabilities { max-width: min(92%, 1400px); }

/* A business's is not that table. Thirteen columns, every one of them asked for
   by name, and capped at 1080px it scrolled sideways inside a box two thirds
   the width of the screen with the space to its right empty — "the liabilities
   table does not fit".
   The overflow-x wrapper around it stays, for a screen narrower than the table
   still is. */
.al-liabilities.al-wide { max-width: none; min-width: 100%; }

.al-table th, .al-table td {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
/* the description is the one column that can give way, so it does */
/* "Description column wider; expand to full width when editing; long text wraps
   instead of being cut."

   It was held to 220px and truncated with an ellipsis, so a description longer
   than a few words could not be read at all — and the row it belonged to gave
   no clue there was more. It wraps now and takes what the row can spare. */
.al-table .desc {
  max-width: none; min-width: 220px;
  white-space: normal; overflow-wrap: break-word;
}

/* And the whole width while it is being edited: a description is the field most
   likely to be long and the one hardest to check in a box four words wide. */
.al-table .al-editing .desc,
.al-table tr.al-editing td.desc { min-width: 320px; }
.al-table .al-editing .desc input { width: 100%; }

/* "I just feel like they can be brought in as well." The applications on a
   person: four columns across the width of a panel, and rarely more than a row
   or two in it. */
/* Sized for the four columns it had — application, entity, stage, financed.
   It carries seven now, with an asset description and a contract number among
   them, and 900px put the lender and the contract on two lines each. Still
   capped rather than let loose: a person rarely has more than a row or two here
   and a short table stretched across a wide screen reads worse than a snug one. */
.deals-narrow { max-width: min(100%, 1240px); }

@media (max-width: 1100px) { .deals-narrow { max-width: 100%; } }

/* one save for every row above it */
.al-savebar {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  padding: 10px 16px 14px; border-top: 1px solid var(--line); background: var(--paper);
}

@media (max-width: 1100px) {
  .al-assets, .al-liabilities { max-width: 100%; }
}
.al-table thead th {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); font-weight: 600; padding-top: 0; padding-bottom: 5px;
}
.al-table td:first-child, .al-table th:first-child { padding-left: 16px; }
.al-table .num { text-align: right; white-space: nowrap; }
.al-table .desc { color: var(--muted); }
.al-table .act { text-align: right; white-space: nowrap; width: 1%; padding-right: 16px; }
.al-table tbody tr:last-child td { border-bottom: none; }
.al-none td { color: var(--muted); font-style: italic; }

/* The editing row keeps the reading row's columns — the inputs live in the same
   cells, pointed at a form outside the table. */
.al-editing td { background: #fafbfc; padding-top: 5px; padding-bottom: 5px; }
.al-editing input, .al-editing select {
  width: 100%; padding: 5px 7px; font-size: 12.5px; min-width: 0;
}
.al-editing .num input { text-align: right; }

/* The type dropdown has to hold the longest thing in it.

   "On edit, the Type dropdown needs to be wider" — and the same on add. The
   select is the width of its cell, and the cell was sized by the reading rows
   above it, where the words are short: Vehicles, Credit card. Chosen, "Tax
   debt / ATO payment plan" and "Business or company value" were cut off mid
   word, which on a dropdown is worse than on text — it is the answer he has
   just given and cannot check.

   On the person's two tables only. A business's A&L is thirteen columns with
   their widths already set one by one, and it is not this problem. */
/* Width, not merely a minimum: with three other columns sharing 920px the
   assets table handed the type column 343px of it — a dropdown wider than
   anything that goes in it, and a description box narrower than it should be.
   Named, the slack goes to the description, which can always use it. */
.al-assets th:first-child,
.al-assets td:first-child,
.al-liabilities:not(.al-wide) th:first-child,
.al-liabilities:not(.al-wide) td:first-child { width: 248px; min-width: 248px; }

/* And the frequency column, for the same reason one column over.
   "Fortnightly" is the longest of the five and wants about 72px of text; with
   the select's own padding, border and arrow and the cell's padding either
   side, the column needs about 125. It had 98, and read "Fortnigh⌄". */
.al-liabilities:not(.al-wide) th:nth-child(5),
.al-liabilities:not(.al-wide) td:nth-child(5) { width: 132px; min-width: 132px; }

/* 248, measured rather than guessed: "Tax debt / ATO payment plan" is the
   longest thing in either dropdown and wants 168px of text. The cell gives 16
   to padding and the select another 34 to its own padding, border and arrow,
   so the column has to be about 220 before the words survive. 232 fitted with
   six pixels to spare, which is not enough to be sure of on somebody else's
   machine and somebody else's font. */
.al-na { color: var(--muted); }

.al-link {
  background: none; border: none; padding: 0 6px; cursor: pointer;
  font-size: 12px; font-weight: 600; color: var(--navy); text-decoration: none;
}
.al-link:hover { text-decoration: underline; }
.al-del { color: var(--muted); }
.al-del:hover { color: var(--bad); }

/* A cell that states what is worked out rather than asking for it — the
   maturity, which is the start date plus the term and no longer a box that can
   disagree with them. */
.al-derived { color: var(--muted); font-size: 11.5px; font-style: italic; }

/* "If an asset's financed is paid out, should it not auto save under
   unencumbered assets?" — asked, under the row it is about, because the answer
   is his and the system genuinely does not know it. Tucked under the facility
   rather than beside it: it is a note on that row, not a row of its own, and
   the borrowed left padding lines it up under the lender it belongs to. */
.al-ask td {
  background: #fbf9f4; border-top: none;
  padding: 5px 16px 6px 26px; font-size: 12px; color: var(--muted);
}
.al-ask-q { margin-right: 4px; }
.al-ask .al-link { padding: 0 8px; }
/* the quieter of the two, because saying no is the end of it */
.al-ask-no { color: var(--muted); font-weight: 500; }

/* Dragging a facility into the order he keeps his own sheet in. The row being
   moved fades so the gap it will land in is the thing he is watching. */
/* The one control on a hand-built row: which settled deal it turned out to be.
   Small and quiet — most rows never need it, and the ones that do need it once. */
/* The second way into a continuation: the register rather than the search box.
   On its own line, because it is an alternative to the one above rather than
   another field of it. */
.chain-abn {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--line);
}

/* The Deal column on the schedule.
 *
 * "Make the column wider so Manual entry doesn't wrap. Put Create an app
 * underneath, clearly as a blue link. Make Link to an app also a link."
 *
 * It was a dropdown that submitted the moment it changed and a button that
 * fired a browser confirm — two different gestures for two neighbouring
 * choices, in a column narrow enough to break "Manual entry" over two lines.
 * Both are links now, both open a window, and the column is told to fit its
 * widest line. */
/* It had a floor and nowrap, from before the table was locked to its width.
   Both fought the lock: a floor keeps a column from narrowing with the rest,
   and nowrap makes it push the table out rather than wrap. Its share is set
   with the others above. */
.schedule td[data-col="deal"],
.schedule th[data-col="deal"] { white-space: normal; }

/* ---------------------------------------------------------------------------
   The schedule is locked to the width it has.

   "Trim it back so it doesn't scroll — I didn't see the Edit links till now."
   "Make Serial off by default and stop scrolling — lock it."

   Edit is the last cell of the row, so a table wider than the window put it
   past the edge with nothing on screen to say it was there. Measured at four
   widths, it came to 1440px: fine at 1920, 134px over at 1600, 294px over at
   1440.

   Trimming got it to 1267px with Serial away, which fits 1600 and still not
   1440. Fifteen columns do not fit 1146px at their natural widths, so the
   table is given the width it has rather than the width it wants: fixed
   layout, 100%, and a share for each column. It cannot overflow, so it cannot
   scroll, so nothing can hide off the right.

   The shares are the proportions the columns had measured at 1600px, which is
   why nothing moves at that width or above. Below it they narrow together and
   the prose wraps: at 1440 the tallest row goes 69px to 81 and the table is
   1.6% longer overall; at 1280, 101px. That is the whole cost, and it buys a
   page that reads the same on every screen.

   Percentages rather than pixels because the picker hides columns: what is put
   away leaves its share behind, and the rest take it.
   --------------------------------------------------------------------------- */
table.schedule { width: 100%; table-layout: fixed; }

.schedule th[data-col="facility"],  .schedule td[data-col="facility"]  { width: 6.3%; }
.schedule th[data-col="lender"],    .schedule td[data-col="lender"]    { width: 8.4%; }
.schedule th[data-col="contract"],  .schedule td[data-col="contract"]  { width: 6.7%; }
.schedule th[data-col="repayment"], .schedule td[data-col="repayment"] { width: 6.8%; }
.schedule th[data-col="term"],      .schedule td[data-col="term"]      { width: 3.6%; }
.schedule th[data-col="balloon"],   .schedule td[data-col="balloon"]   { width: 5.5%; }
.schedule th[data-col="start"],     .schedule td[data-col="start"]     { width: 6.5%; }
.schedule th[data-col="maturity"],  .schedule td[data-col="maturity"]  { width: 6.5%; }
.schedule th[data-col="exposure"],  .schedule td[data-col="exposure"]  { width: 6.6%; }

/* The one carrying prose, and the reason any of this was looked at: it was
   96px and fell down seven lines. Its share is the largest on the table. */
.schedule th[data-col="asset"],     .schedule td[data-col="asset"]     { width: 15%; }

/* Seventeen characters with nowhere to break, so it is told where. */
.schedule th[data-col="vin"],       .schedule td[data-col="vin"]       { width: 9.9%; overflow-wrap: anywhere; }
.schedule th[data-col="engine"],    .schedule td[data-col="engine"]    { width: 7%; overflow-wrap: anywhere; }
.schedule th[data-col="rego"],      .schedule td[data-col="rego"]      { width: 6%; }
.schedule th[data-col="deal"],      .schedule td[data-col="deal"]      { width: 9.2%; }
.schedule th:last-child,            .schedule td:last-child            { width: 2.8%; }

/* Fixed strings do not wrap, so a smaller face makes the column narrower
   without costing a line: a VIN is seventeen characters either way. */
.schedule td[data-col="vin"], .schedule th[data-col="vin"],
.schedule td[data-col="engine"], .schedule th[data-col="engine"],
.schedule td[data-col="contract"], .schedule th[data-col="contract"],
.schedule td[data-col="rego"], .schedule th[data-col="rego"] { font-size: 11.5px; }

/* Pinned as well, which costs nothing now and holds if a column is ever added
   back that pushes the table out again. No shadow: with nothing to scroll past
   it would draw a line down the page for no reason. */
.schedule th:last-child,
.schedule td:last-child { position: sticky; right: 0; z-index: 1; background: #fff; }
.schedule tbody tr:nth-child(even) td:last-child { background: var(--paper); }
.schedule tr.fy-head th:last-child { background: var(--navy-deep); }
.schedule tr.fy-total td:last-child { background: var(--paper); }


.manual-entry { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.manual-entry-label { color: var(--muted); }

/* Both actions read as links, because both are. */
.manual-entry .link {
    background: none; border: none; padding: 0; cursor: pointer;
    font-size: 11.5px; font-weight: 600; color: var(--navy); text-decoration: none;
}
.manual-entry .link:hover { text-decoration: underline; }

/* A list to read rather than a dropdown to guess at: he is choosing which
   application this facility is, and the asset is how he tells them apart. */
.link-deal-list {
    width: 100%; font-size: 12.5px; padding: 4px;
}

/* No grab cursor here. "Commitment schedule does not need drag to sort — only
   the A&Ls for business and individual", so the drag came off this table and
   the hand it was pointed with did not: every row offered to be picked up and
   none of them could be. Nothing sets is-dragging on this table either — that
   belongs to the A&L's handler — so both rules were describing a gesture that
   no longer exists. The arrow is the truth. */

/* The same, on the A&L tables that now drag. A row a client's A&L is arranged
   in is a row he means to be where he put it, so it says it can be moved before
   he tries: the cursor over a draggable row is a grab hand. */
.al-table tbody[data-al-sortable] > tr[data-al-order] { cursor: grab; }
.al-table tr.is-dragging { opacity: .4; cursor: grabbing; }
.al-table tr.is-dragging td { background: var(--paper); }

.al-add {
  display: block; width: 100%; text-align: left;
  padding: 9px 16px 12px; background: none; border: none; cursor: pointer;
  font-size: 12.5px; font-weight: 600; color: var(--navy);
}
.al-add:hover { background: #fafbfc; }

/* Seven columns of numbers will not fit every screen; the table scrolls rather
   than the page. */
.al-liabilities { min-width: 780px; }
.al-section > .al-table { display: table; }
.al-section { overflow-x: auto; }

/* ---------------------------------------------------------------------------
   D6 — "Other" adds the thing over the page rather than navigating to it.

   "Rather than migrating to the page why not a popup box for just the name…
   keeps him on page with no need to save deal info."
   --------------------------------------------------------------------------- */
.qa-back {
  position: fixed; inset: 0; z-index: 900;
  background: rgba(18, 28, 38, .38);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 12vh 16px 16px;
}
.qa-box {
  background: #fff; border-radius: 10px; width: 100%; max-width: 380px;
  padding: 18px 20px 16px; box-shadow: 0 18px 44px rgba(18, 28, 38, .26);
}
.qa-box h4 { margin: 0 0 4px; font-size: 15px; color: var(--ink); }
.qa-box p { margin: 0 0 12px; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.qa-box input { width: 100%; padding: 8px 10px; font-size: 13px; }
.qa-error { margin-top: 8px; font-size: 12px; color: var(--bad); }
.qa-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 14px; }

/* The supplier panel, which opens under the row rather than over the page.
 *
 * "If this option is clicked open a panel underneath with all the field to add
 * a new supplier."
 *
 * A box floats because it holds one field. Thirteen belong in the flow: the
 * application above stays where it was, nothing is covered, and the deal being
 * typed is never behind a scrim. Inset and ruled so it reads as a thing being
 * added to the application rather than another part of it.
 */
.qa-panel {
  margin: 2px 0 12px; padding: 14px 16px 16px;
  background: #fbfcfd; border: 1px solid var(--line); border-radius: 8px;
}
.qa-panel-head { margin-bottom: 12px; }
.qa-panel-head h4 { margin: 0 0 3px; font-size: 14px; color: var(--ink); }
.qa-panel-head p { margin: 0; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.qa-panel .qa-actions { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }

/* ---------------------------------------------------------------------------
   D4 — the commission the two fee boxes add up to, beside the percentage.

   "Brokerage percentage as a small box, and then next to that, commission."
   Read-only: a third box to type it in would be a third answer to the same
   question.
   --------------------------------------------------------------------------- */
.commission-readout {
  display: flex; align-items: stretch; gap: 8px;
}
.commission-figure {
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: baseline; justify-content: space-between; gap: 6px;
  padding: 8px 10px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 8px;
}
.commission-figure.is-lead { background: #fff; border-color: var(--gold); }
.commission-amount {
  font-size: 13px; font-weight: 700; color: var(--ink);
  overflow-wrap: anywhere;
}
.commission-tag {
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}

/* ---------------------------------------------------------------------------
   D7 — the confirmation banner stops sitting there.
   --------------------------------------------------------------------------- */
.alert { position: relative; padding-right: 38px; }
.alert-x {
  position: absolute; top: 50%; right: 10px; transform: translateY(-50%);
  background: none; border: none; cursor: pointer;
  font-size: 18px; line-height: 1; padding: 2px 5px; border-radius: 6px;
  color: inherit; opacity: .5;
}
.alert-x:hover { opacity: 1; }

/* A percentage box the width of a percentage, and the commission it produces
   given the rest of the row. Half each made a four-character field enormous and
   squeezed two dollar figures until they wrapped. */
.form-row-pct {
  display: grid; gap: 10px; margin-bottom: 9px;
  grid-template-columns: 150px 1fr;
}
.form-row-pct > .field { margin-bottom: 0; min-width: 0; }

@media (max-width: 900px) {
  .form-row-pct { grid-template-columns: 1fr; }
}

/* The commission panel, three fields to a row.

   "The Brokerage fields are too small — let's make them wider, with Brokerage
   ex, inc and % on one line, then Origination Fee underneath, then Commission
   ex, inc and received underneath."

   Two figures crammed into half a row is what made $2,045.45 read as "2045.4".
   Each field takes a third of the panel now, which is a little over twice what
   it had. */
.form-row-fees {
  display: grid; gap: 10px 14px; margin-bottom: 9px;
  grid-template-columns: repeat(3, 1fr);
  align-items: start;
}
.form-row-fees > .field { margin-bottom: 0; min-width: 0; }

/* "Account keeping ex GST still wraps — just make ex GST etc on a second line.
   Only for Account Keeping."

   It is the longest of the four names and the only one that does not fit, so it
   is the only one broken. Which side of the label wraps is otherwise the
   browser's guess, and it was splitting the name itself while leaving "ex GST"
   stranded below. Put deliberately: the name on one line, which side of GST it
   is on the next. Its two labels match each other, which is what has to line
   up — the other rows are their own rows. */
.form-row-fees label[for="account_keeping_fee_ex_gst"] .field-note,
.form-row-fees label[for="account_keeping_fee"] .field-note {
  display: block; line-height: 1.25;
}
.form-row-fees .unit-input,
.form-row-fees input { width: 100%; }

/* the readouts sit where an input would, so the row lines up across it */
.form-row-fees .commission-readout { margin: 0; }

@media (max-width: 900px) {
  .form-row-fees { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 620px) {
  .form-row-fees { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------------
   F1 — client status on the heading line.

   "Active, semi-active and dormant next to the personal details on this line.
   If I clicked active, it was green. Semi-active, orange. Dormant, red. And
   then you remove that column and save some space."

   It had a pill in the heading and a row of its own beneath saying the same
   thing twice. Where he stands is the colour that is lit; the rest are faded.
   --------------------------------------------------------------------------- */
.status-inline { display: inline-flex; gap: 5px; align-items: center; margin: 0; }
.status-chip {
  font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 999px; cursor: pointer; white-space: nowrap;
  font-family: inherit; line-height: 1.5;
  /* unlit: the colour is there but drained, so the lit one is unmistakable and
     the others still read as the thing they would set */
  background: #fff; border: 1px solid var(--line); color: #b6bfc5;
}
.status-chip:hover { border-color: currentColor; }

.status-chip.is-active:hover { color: var(--ok); }
.status-chip.is-semi_active:hover { color: var(--warn); }
.status-chip.is-dormant:hover { color: var(--bad); }

.status-chip.on { color: #fff; }
.status-chip.is-active.on { background: var(--ok); border-color: var(--ok); }
.status-chip.is-semi_active.on { background: var(--warn); border-color: var(--warn); }
.status-chip.is-dormant.on { background: var(--bad); border-color: var(--bad); }

/* "Make Remove link red please" — it was grey until hover, on the reasoning
   that a destructive action should not shout. He wants to find it. */
.slot-act.is-bad { color: var(--bad); }
.slot-act.is-bad:hover { color: var(--bad); }

/* F2 — a business is active or dormant, with the reason beside it.
   Dormant is the exception and reads as one; active is the ordinary state and
   should not be a green flash on every record, so it takes the muted treatment
   a person's Active does not. */
.status-chip.is-dormant.on { background: var(--bad); border-color: var(--bad); }
.status-chip.is-dormant:hover { color: var(--bad); }

/* The reason: text until it is clicked, then a box on the same line. Kept
   inside the status form, so typing a reason and pressing a status is one
   action rather than two. */
.status-why {
  background: none; border: none; padding: 0 2px; cursor: pointer;
  font-family: inherit; font-size: 11.5px; color: var(--muted);
  max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.status-why:hover { color: var(--navy); text-decoration: underline; }
.status-why-input {
  font-size: 11.5px; padding: 3px 7px; min-width: 150px; flex: 0 1 220px;
}

/* The reason is asked for before dormant is set, not after — so the box and its
   confirm sit where the chip was. */
.status-ask { display: inline-flex; align-items: center; gap: 6px; }

/* ---------------------------------------------------------------------------
   F4 — the remaining forms, condensed.

   "The application edit form was condensed. The new-business, new-deal, person
   and A&L forms have not been." Five panels one under another turn a fact-find
   into a scroll; the same two columns the deal form got put each of them on one
   screen. Deliberately two, not three: a company name and a street address need
   room to read, and the deal form only gets three because its middle column is
   nothing but figures.
   --------------------------------------------------------------------------- */
.record-form .panel { margin-bottom: 0; }
.record-form .panel-head { padding: 7px 16px; }
.record-form .panel-head h3 { font-size: 12.5px; }
.record-form .panel-body { padding: 12px 16px; }

.record-form .form-panels {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 12px; align-items: start;
}

/* A panel that has to have the whole width: the ABR name search puts a results
   list under the box, and "Relationships & notes" is three across. */
.record-form .form-panels > .span-all { grid-column: 1 / -1; }

/* Panels grouped into one column, as on the deal form — the column is then as
   tall as its contents rather than as tall as the row it was placed in. */
.record-form .form-col {
  display: flex; flex-direction: column; gap: 12px; min-width: 0;
}

/* a half-width column is not the place for a four-across row */
.record-form .form-panels .form-row-3,
.record-form .form-panels .form-row-4 { grid-template-columns: 1fr 1fr; }

/* A form opened inside the panel it belongs to has the width of that panel, not
   of the page — and on a person that panel is one column of three.
   "Trying to edit gives a broken screen… put the three blocks for Personal
   details under each other."

   Two columns of two-column rows inside a third of a page is four columns of
   nothing: first names came out clipped mid-word and half the labels wrapped.
   So a form in a panel is one column, whatever it is when it has a page to
   itself.

   Scoped to .panel-edit rather than to the person's form, because it is the
   container that is narrow: the same form on /individuals/{id}/edit still gets
   its two columns, and the next form opened in a panel is right without anybody
   remembering this. */
.panel-edit .record-form .form-panels { grid-template-columns: 1fr; }
.panel-edit .record-form .form-panels > .span-all { grid-column: auto; }
.panel-edit .record-form .form-col { gap: 12px; }

/* and the rows inside those panels keep their three and four across, which is
   where the width was wanted */
.panel-edit .record-form .form-panels .form-row-3 { grid-template-columns: 1fr 1fr 1fr; }
.panel-edit .record-form .form-panels .form-row-4 { grid-template-columns: repeat(4, 1fr); }

/* The same disease on a contact, and worse. A person's panel is a third of the
   page; a contact's Details panel is the 340px column of .layout, which is the
   right width to read an identity card and the wrong width to edit one. Four
   fields across 340px is seventy pixels each, and the media query that would
   have collapsed them keys off the viewport rather than the container, so on a
   wide screen it never fired.

   "Do not span the page — only wider." So the column grows while the form is
   open and the second column stays beside it, rather than the panel taking the
   whole width. 600px is two comfortable fields plus the gap, which is what the
   form is laid out for. */
.layout.is-editing { grid-template-columns: minmax(0, 600px) 1fr; }

/* it is a column of a grid, so it needs somewhere to grow into */
@media (max-width: 1180px) {
  .layout.is-editing { grid-template-columns: minmax(0, 460px) 1fr; }
}

/* Nothing goes four across inside a panel, whatever the form thinks it is.
   The contact form is not a .record-form, so the rules above never reached it —
   this one is scoped to the container, which is the thing that is narrow. */
.panel-edit .form-row-4 { grid-template-columns: repeat(2, 1fr); }

/* Stacked instead of columned, where the fields are long strings rather than
   figures: "The business & Trading address & contact are side by side columns
   and two small — make them full width and one above the other."

   The panels supply their own spacing here, since there is no grid gap to do
   it, and the rows inside them keep their three and four across — which is
   where the width was wanted in the first place. */
.record-form.is-stacked .panel { margin-bottom: 12px; }
.record-form.is-stacked .panel:last-child { margin-bottom: 0; }

/* A form is a column, not a page.

   "https://meraki.sentient-ai-systems.com/businesses/new is the same full width
   over large fields — it needs to match edit style." The edit he was comparing
   against is the in-place one on the record, which renders in the first of
   three columns and is therefore about a third of the screen. The same form on
   its own page had the whole width, so a suburb box was six inches long.

   A cap rather than a copy of that third: 940px is a comfortable measure for
   two columns or one, and it changes nothing where the container is already
   narrower — which is exactly the in-place edit he says looks right. */
.record-form.is-stacked { max-width: 940px; }

/* Two columns while it is being created, filling the screen: "two columns side
   by side to fill the screen — second column starts from Trading address &
   contact."

   Not on the record. The in-place edit is already the first of three columns
   and has no second one to give, which is why the same partial reads its own
   layout off whether the business exists yet. */
.record-form.is-two-up {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 12px; align-items: start;
}
.record-form.is-two-up .form-col {
  display: flex; flex-direction: column; gap: 12px; min-width: 0;
}
.record-form.is-two-up .panel { margin-bottom: 0; }

@media (max-width: 1000px) {
  .record-form.is-two-up { grid-template-columns: 1fr; }
}

@media (max-width: 1000px) {
  .record-form .form-panels { grid-template-columns: 1fr; }
  .record-form .form-panels .form-row-3 { grid-template-columns: 1fr 1fr 1fr; }
}

/* ---------------------------------------------------------------------------
   B1 — the task, opened.

   "I can't do anything with this task. It means nothing to me. It's just a
   note… I can't select it, I can't change it, I can't say what's happened."
   --------------------------------------------------------------------------- */
.task-head {
  display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap;
  margin-bottom: 12px;
}
.task-head h2 {
  margin: 0; font-size: 18px; color: var(--ink); line-height: 1.3;
  overflow-wrap: anywhere;
}
.task-head h2.is-done { color: var(--muted); text-decoration: line-through; }
.task-head-sub { margin-top: 3px; font-size: 12.5px; color: var(--muted); }
.task-head-sub .due-late { color: var(--bad); font-weight: 700; }
.task-head-actions {
  margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.task-head-actions form { margin: 0; }
.task-push { display: inline-flex; align-items: center; gap: 6px; }

/* B2 — what has been done, on the record it was done on.

   "Active ones only display by default - but a button / link 'Show Completed
   Tasks' displays these - possibly in a lighter font style to differentiate
   from active tasks." */
.is-done-list { background: var(--paper); }
.is-done-list .task-table .cell-main { color: var(--muted); font-weight: 500; }
/* a completed list is reference: its heading row would only repeat the one above */
.is-done-list .task-table thead { display: none; }

/* B4 — "smaller filter chips, less space around everything." */
.chip-sm { font-size: 10.5px; padding: 2px 8px; }
.sort-by { display: inline-flex; align-items: center; gap: 5px; }

/* ---------------------------------------------------------------------------
   A1 — the business has changed since this application took its copy.

   "That deal keeps what it had, and the deal shows a quiet note … one-click
   bring it across." Quiet: the deal is not wrong, and on a settled application
   its copy is the record of who stood behind the money.
   --------------------------------------------------------------------------- */
/* The notice and the link that answers it, under the panel they are about.
   It spanned the whole top row under the stage strip until 10 September, with
   its control in the column below — "these are disconnected". Not a grid child
   any more: it sits in the left-hand column.

   One run of text, not a stack: the link follows the last word of the sentence
   rather than taking a line of its own — "can it stay on the same line as the
   message instead of a new line to save space?" A flex column gave it that line
   at every width; inline, it only takes one when the sentence fills the last. */
.drift {
  padding: 9px 14px; margin: -6px 0 18px;
  background: var(--paper); border: 1px solid var(--line);
  border-left: 3px solid var(--gold); border-radius: 0 8px 8px 0;
  font-size: 12.5px; line-height: 1.5;
}
.drift-said { display: inline; color: var(--muted); }
.drift-said strong { color: var(--ink); font-weight: 700; }
.drift-said span { display: inline; }
.drift form { display: inline; margin: 0; }
.drift-foot button { margin-left: 6px; }

/* Everything the validator refused, named. A form with twenty-three validated
   fields and three error messages under them reloads looking identical and says
   nothing — which is indistinguishable from the button not working. */
.alert-list { margin: 6px 0 0; padding-left: 18px; }
.alert-list li { margin: 2px 0; line-height: 1.5; }

/* Suburb, state, postcode — each the width of what goes in it rather than an
   equal third. "Suburb needs to be wider — postcode can trim back a little."
   A suburb is "Sunshine Beach"; a state is three letters and a postcode four
   digits, and neither grows. */
.form-row-address {
  display: grid; gap: 10px; margin-bottom: 9px;
  grid-template-columns: 1fr 90px 110px;
}
.form-row-address > .field { margin-bottom: 0; min-width: 0; }

@media (max-width: 700px) {
  .form-row-address { grid-template-columns: 1fr 1fr; }
}

/* ---------------------------------------------------------------------------
   Printing.

   "The schedule stays printable on its own — lenders ask for the commitment
    schedule, not the A&L."

   There was no print stylesheet at all, so Ctrl-P gave the sidebar, the tab
   strip, the chips and the export panel wrapped around the thing he wanted. The
   PDF export is the polished answer and stays the one to send; this is for the
   times he just wants it on paper without a round trip through a download.

   Everything that is a control rather than a fact goes. What is left is the
   heading, the totals and the table.
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   How far an upload has got.

   Drawn under the form that is sending, by _live_form. It exists because the
   alternative was nothing at all: over a long link a licence takes two to three
   seconds to arrive, and for those seconds the only feedback was a disabled
   button. One upload in the access log took seventeen and came back empty, and
   there was no way to tell that from a click that had missed.

   Deliberately quiet — a line, not a dialog. It appears when something is being
   sent and is taken out of the page when the answer lands.
   --------------------------------------------------------------------------- */
.upload-progress {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
}

.upload-progress-track {
    flex: 1 1 auto;
    max-width: 260px;
    height: 4px;
    border-radius: 2px;
    background: var(--line);
    overflow: hidden;
}

.upload-progress-fill {
    height: 100%;
    width: 0;
    border-radius: 2px;
    background: var(--gold-deep);
    transition: width 140ms linear;
}

/* No percentage to give — being re-encoded before it is sent, or sent and
   waiting on the answer. A stripe that moves says working; a bar sitting full
   says finished, which at that moment it is not. */
.upload-progress.is-waiting .upload-progress-fill {
    background-image: linear-gradient(
        110deg,
        var(--gold-deep) 0 32%, var(--gold) 32% 68%, var(--gold-deep) 68% 100%
    );
    background-size: 220% 100%;
    animation: upload-working 1100ms linear infinite;
}

@keyframes upload-working {
    from { background-position: 100% 0; }
    to   { background-position: -20% 0; }
}

.upload-progress-said {
    flex: 0 0 auto;
    font-size: 12px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

@media print {

    /* Nobody prints a progress bar, and it must not reach a settlement pack.
       Here rather than in a block of its own: PrintedScheduleFitsThePageTest
       reads the first @media print in the file and asserts against it, so a
       second one earlier in the sheet hides the real one from the tests. */
    .upload-progress { display: none; }
  @page { margin: 12mm; size: landscape; }

  /* .chrome is the sticky wrapper around the topbar and the tabs. Hiding only
     its children would leave an empty sticky box holding the top of the page. */
  .sidebar, .chrome, .topbar, .tabstrip, .filter-bar,
  .alert, .panel-toggle, .btn, .btn-link, .chip, .column-picker,
  .export-options, #export-panel, .edit-toggle, .fy-toggle,
  .task-add, .note-tools { display: none !important; }

  /* the grid exists to hold the sidebar beside the content */
  .layout { display: block !important; }
  .content { padding: 0 !important; }
  body { background: #fff; }

  /* A panel is a card on screen and a section on paper: the shadow and the
     rounded corner both print as grey fuzz. */
  .panel {
    border: 0; box-shadow: none; border-radius: 0;
    margin-bottom: 10mm; break-inside: auto;
  }
  .panel-head { border-bottom: 1.5pt solid #1b5772; padding-left: 0; padding-right: 0; }

  /* it scrolls sideways on screen; on paper there is nowhere to scroll to */
  .schedule-scroll, [style*="overflow-x"] { overflow: visible !important; }

  table.schedule { font-size: 8pt; width: 100%; }
  table.schedule th, table.schedule td { padding: 3pt 4pt; }

  /* a facility split across a page break is a facility misread */
  table.schedule tr { break-inside: avoid; }
  table.schedule thead { display: table-header-group; }
  /* nothing floats above a printed page */
  .schedule-float { display: none !important; }
  .schedule tr.fy-head th { break-after: avoid; }

  /* the editor behind a row is not part of the schedule */
  .schedule tr.row-editor, .schedule .edit-row { display: none !important; }

  /* links read as links on screen and as blue words on paper */
  a { color: inherit; text-decoration: none; }

  .stat-row { break-inside: avoid; }

  /* The four figures are a header line on paper, not four cards down a page.

     Chrome lays a printed sheet out at around 724–774px wide, which trips the
     820px phone breakpoint below and stacks the grid one to a row. The result
     was four full-width boxes and a single facility on sheet one, with the
     schedule itself pushed onto sheet two. Stated again here, after those
     breakpoints, so the paper stops inheriting a phone layout.

     Smaller with it: a card is sized to be read across a desk, and the figure
     it carries is a heading on a printout, not the subject of it. */
  .stats {
    grid-template-columns: repeat(4, 1fr);
    gap: 6pt;
    margin-bottom: 6mm;
    break-inside: avoid;
  }
  .stat { border-radius: 0; padding: 5pt 7pt 4pt; }
  .stat::after { width: 2pt; }
  .stat-label { font-size: 6.5pt; letter-spacing: .6px; }
  .stat-value { font-size: 13pt; margin-top: 2pt; letter-spacing: 0; }
  .stat-sub { font-size: 6.5pt; margin-top: 1pt; }
}

/* ---------------------------------------------------------------------------
   Bands — the application page, section C.

   "It's jumping from page to page to page, and even me trying to help me
   explain it to you, I even got lost in where I was at and what I was doing."

   A band is a full-width strip that opens where it stands. Across the page and
   not down a column, on his instruction and for his reason: "that way, I can
   see the deal at the same time" — the loan and the asset stay above whatever
   he has opened.
   --------------------------------------------------------------------------- */
.band {
  background: var(--paper); border: 1px solid var(--line); border-radius: 4px;
  margin-bottom: 8px;
}
.band.is-open { border-color: var(--navy); }

/* The whole line is the control. A caret you have to hit is a small target on a
   strip that is otherwise the width of the page. */
.band-head {
  display: flex; align-items: baseline; gap: 10px; width: 100%;
  padding: 10px 14px; background: none; border: none; cursor: pointer;
  text-align: left; font: inherit;
}
.band-head:hover { background: #fafbfc; }
.band.is-open .band-head { border-bottom: 1px solid var(--line); }

.band-caret { color: var(--muted); font-size: 11px; width: 10px; flex: none; }
.band-title { font-weight: 600; font-size: 13px; color: var(--ink); flex: none; }

/* What is in it, read without opening it: the ABN, the net position, the
   registration. Ellipsised rather than wrapped — a band is one line. */
.band-summary {
  color: var(--muted); font-size: 12px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.band-count {
  margin-left: auto; flex: none; color: var(--muted); font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.band-body { padding: 12px 14px; }
/* a panel inside a band has already been framed by the band */
.band-body > .panel { border: none; border-radius: 0; margin: 0; }
.band-body > .panel > .panel-head { padding-top: 0; }

@media (max-width: 700px) {
  .band-summary { display: none; }
}

/* The line at the top of a new application once it has been saved once.

   "This appears once step 1 of the deal is saved and there is a lender to build
   this against." It says the record exists — because nothing else on the page
   changes enough to make that obvious — and offers the finished application
   without sending him there. */
.build-bar {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: 14px;
  background: #f4f8f4; border: 1px solid #cfe0cf; border-radius: 4px;
}
.build-said { font-size: 12.5px; color: var(--ink); }
.build-bar .btn { margin-left: auto; }

/* The A&L's own row editor, the same shape as the schedule's.

   "Editing a facility opens a new pane — it should be a dropdown in the row."
   The schedule answered that; this panel was still walking him to a page, which
   on the new application means walking him off the deal he is keying. */
#assets-and-liabilities tr.facility-edit > td {
  background: var(--paper); padding: 12px 14px; border-bottom: 2px solid var(--line);
}
#assets-and-liabilities tr.facility-edit .panel { margin-bottom: 10px; box-shadow: none; }
#assets-and-liabilities tr.facility-edit .panel:last-of-type { margin-bottom: 12px; }

/* The moved-in date, set on the current-address row itself.

   The row marks an undated current address in red and it counts nothing
   towards the three years a lender wants, so the row is where the date is
   entered — it used to be two folds away inside Edit → Lender detail, which
   read as not being able to enter one at all. */
.addr-date-edit {
  margin-left: 8px; background: none; border: none; padding: 0;
  font: inherit; font-size: 11.5px; cursor: pointer;
}
.addr-date-form {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
  margin-top: 6px;
}
.addr-date-form label { font-size: 11.5px; color: var(--muted); }
.addr-date-form input { width: 150px; }
.addr-date-form .field-error { flex-basis: 100%; margin: 0; }

/* A row that changed under him without the page moving.

   "On editing a row just refresh the row, not the whole page." The row is
   swapped in place, so it says so for a moment — otherwise a save with nothing
   visibly different reads as a save that did not happen. */
#assets-and-liabilities tr.is-saved > td { background: var(--gold-soft); }
#assets-and-liabilities tr > td { transition: background 600ms; }

/* Adding an asset: across the row, with the fields named.

   "The form is too cramped and has no field headers — the row for the addition
   can go full width and have ample headers and labels for fields." It was four
   boxes squeezed into four columns sized for reading a table, with the column
   heading three rows up doing the work of a label. */
/* The add-a-facility form, told apart from the rows above it.

     "It is indistinct from the rows without a header telling me what it is."

   It sat on #fafbfc, which against a white table is not a difference anyone
   notices while looking for a form they were not shown. A tinted ground, a rule
   above it and a gold edge down the side, so that when the page scrolls to it
   there is no question which part of the screen is new. */
/* The way in to adding a facility, where the rows run out — "add liability
   belongs in the row, not only top-right". Quiet, because it sits under sixty
   rows of figures and is not the thing being read. */
.al-add-here > td { padding: 8px 16px; border-bottom: none; }

/* What the live facilities are held against, counted towards what he owns.
   Quieter than the outright figure beside it: it is derived from the schedule
   above rather than recorded here, and a facility with no value recorded says
   so rather than counting as nothing in silence. */
.al-financed { color: var(--muted); }
.al-unvalued { color: var(--warn); }

.al-add-row > td {
  background: var(--paper); padding: 0;
  border-top: 2px solid var(--line);
  box-shadow: inset 3px 0 0 var(--gold);
}
.al-add-form { padding: 14px 16px 12px; }

.al-add-head {
  font-size: 13px; font-weight: 700; color: var(--navy);
  letter-spacing: .01em; margin-bottom: 12px;
  padding-bottom: 8px; border-bottom: 1px solid var(--line);
}
.al-add-form .form-row-2,
.al-add-form .form-row-3,
.al-add-form .form-row-4 { margin-bottom: 10px; }
.al-add-form label { font-size: 11.5px; }
.al-add-form input, .al-add-form select {
  width: 100%; padding: 6px 8px; font-size: 12.5px;
}
.al-add-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* The add-an-asset row's own grids.

   "Make the Type field a little wider to fit Plant and Equipment properly and
   add Valued as At on the same row. Then the rows underneath can be Year
   (smaller), Make, Model, VIN, Registration (smaller)."

   Named columns rather than four equal ones: a type, a description and a date
   do not want the same width, and "Plant and equipment" was clipping inside a
   quarter. */
.al-row-asset,
.al-row-vehicle { display: grid; gap: 12px; margin-bottom: 10px; }

.al-row-asset { grid-template-columns: 1.5fr 2.6fr 1.1fr 1.2fr; }
.al-row-vehicle { grid-template-columns: .7fr 1.3fr 1.8fr 1.6fr .9fr; }

.al-row-asset > .field,
.al-row-vehicle > .field { margin-bottom: 0; }

@media (max-width: 1100px) {
  .al-row-asset { grid-template-columns: 1fr 1fr; }
  .al-row-vehicle { grid-template-columns: repeat(3, 1fr); }
}

/* And the table gives it room. Half the page was right for four columns of
   reading — "same shape but full width, reduce width to 50% for now, may need
   to adjust later" — and this is later: the add row lives inside this table and
   four labelled fields do not fit in half a page.

   On the business only. A person's declared A&L keeps the 50% he asked for. */
.al-assets.al-roomy { max-width: min(74%, 1000px); }

/* The add-a-facility row's grids, one per group of fields.

   Named columns rather than equal ones: a contract number and a date do not
   want the same width as an asset description. */
.al-row-fac,
.al-row-fac-terms,
.al-row-fac-stated,
.al-row-fac-asset,
.al-row-fac-ident { display: grid; gap: 12px; margin-bottom: 10px; }

/* Facility · Lender · Lender name · Contract no. */
.al-row-fac { grid-template-columns: 1.3fr 1.5fr 1.5fr 1.5fr; }

/* The contract. Six boxes at most and none of them a long number, so they are
   deliberately small — "it's the preferred default, but smaller field sizes". */
.al-row-fac-terms { grid-template-columns: repeat(6, minmax(0, 1fr)); }

/* And the exception under it, which is two boxes and should look like two
   rather than being stretched across the page to match the row above. */
.al-row-fac-stated { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 46%; }

/* Year · Make · Model · Registration — a year is four digits and a make is one
   word, so neither wants a quarter of the page. */
.al-row-fac-asset { grid-template-columns: .6fr 1.1fr 1.6fr 1.1fr; }

.al-row-fac-ident { grid-template-columns: 1.6fr 1.4fr; max-width: 60%; }

.al-row-fac > .field,
.al-row-fac-terms > .field,
.al-row-fac-stated > .field,
.al-row-fac-asset > .field,
.al-row-fac-ident > .field { margin-bottom: 0; }

@media (max-width: 1100px) {
  .al-row-fac,
  .al-row-fac-terms,
  .al-row-fac-asset { grid-template-columns: repeat(3, 1fr); }
  .al-row-fac-stated,
  .al-row-fac-ident { grid-template-columns: repeat(2, 1fr); max-width: 100%; }
}

/* Both add forms are the same width.

   The liabilities table is deliberately wide — thirteen columns — but the form
   for adding one is not a table, and stretched across all of it the fields were
   further apart than they are worth reading across. The same cap the assets
   table already puts on its own.  */
.al-add-form { max-width: min(74%, 1000px); }

@media (max-width: 1100px) { .al-add-form { max-width: 100%; } }

/* The schedule's lender filter, beside the financial-year toggle.

   "A dropdown box before group by financial year — default is All lenders then
   a list of active lenders in the schedule." It replaces the row of chips that
   came off in August: thirteen of them on a real client, above the thing he
   came to read. */
.schedule-lender {
  font-size: 12px; padding: 3px 6px; max-width: 200px;
  border: 1px solid var(--line); border-radius: 4px; background: #fff;
}

/* A label that is there for a screen reader and not for the page. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* The record panel's task table keeps to its columns.

   "Delete button is part obscured in the panel — being pushed out."

   Auto layout sizes a column to its content, so a table grows wider than the
   panel holding it, and a panel clips. The assignee marker is what tipped it:
   JASCHA MANALUNGSUNG beside a title, on a table already carrying six columns
   in half a page.

   Fixed layout instead, so the split stays 50/50 and the table fits it. That
   needed Task's width changed too, and this is the part I got wrong first
   time: the column is declared 100%, which auto layout reads as a hint and
   tempers, but fixed layout takes literally — the whole table width, and then
   the five px columns on top of it. It clipped worse, not better. Under fixed
   layout Task is left to size itself, which takes exactly the remainder.

   A long title or a long name then wraps inside the cell rather than pushing
   Delete off the edge. The full-width list is untouched — it has the room. */
.task-table-compact { table-layout: fixed; }
.task-table-compact .cell-main,
.task-table-compact .cell-sub { overflow-wrap: anywhere; }
.task-table-compact .tag { margin-left: 5px; }

/* The A&L reorder handle.

   The whole row used to be draggable, which meant a row could not have a word
   selected in it: "the inability to copy text from the fields to paste into
   another field — as the whole field is draggable". He is copying VINs and
   contract numbers out of these rows and into lender portals, so the row is
   ordinary selectable text now and this one handle moves it.

   Quiet until the row is under the pointer. It is a control he uses rarely and
   a column of dots down the table would read as content. */
/* Out of the flow, pinned to the left edge of the cell.

   "Fixed left, as text wraps under it." Inline, it was part of the first line
   only — so a description long enough to wrap put its second line underneath
   the hand. Absolute, with the cell padded to make room, the text has a
   straight left edge however many lines it runs to. */
.al-grip {
    position: absolute;
    left: 6px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    color: var(--line);
    cursor: grab;
    user-select: none;
    line-height: 1;
    transition: color 120ms;
}

/* The cell it is pinned inside, and the room it is given. */
tbody[data-al-sortable] > tr[data-al-order] > td:first-child {
    position: relative;
    padding-left: 24px;
}

tr:hover > td > .al-grip { color: var(--muted); }
.al-grip:hover { color: var(--navy); }
.al-grip:active { cursor: grabbing; }

/* Everything else in the row is text to be read and copied. */
tbody[data-al-sortable] > tr[data-al-order] { user-select: text; }

/* ---------- the foot of a business page ---------- */

/* "Move the document slots to the bottom of the page far left, with Record now
   far right, and a middle column for Other Documents separately. As there are
   slots for 4 named documents, Other Documents can be a panel the same height,
   making it easy to drag multiple documents into this large area."

   The three stretch to match rather than each stopping at its own content, so
   the loose pile is as tall as the named slots beside it — which is the point:
   a big target is easier to drop an armful onto than a strip. */
.trio-files { align-items: stretch; }
.trio-files > div { display: flex; }
.trio-files > div > .panel { flex: 1 1 auto; display: flex; flex-direction: column; }

/* The panel body takes the slack, and the drop zone inside it takes the slack
   from that — so the dashed area grows to fill whatever height the named slots
   set, instead of leaving dead space under it. */
.trio-files > div > .panel > [x-show] { flex: 1 1 auto; display: flex; flex-direction: column; }
.trio-files .slots { flex: 1 1 auto; display: flex; flex-direction: column; }
.trio-files .slots > .drop-many { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; }

/* A tall dashed box wants a little more air than a strip does. */
.trio-files .drop-many { padding: 14px; min-height: 120px; }

/* Narrow screens: the three stack rather than squeezing a drop zone to nothing. */
@media (max-width: 1200px) {
    .trio-files { grid-template-columns: 1fr; }
    .trio-files .drop-many { min-height: 90px; }
}

/* A chip is sometimes a link and sometimes a button.

   "Selecting Show 1 settled causes a page refresh — can it just hide and reveal
   rows?" It became a button when it stopped navigating, and a button brings the
   browser's own font and cursor with it. */
button.chip {
    font-family: inherit;
    font-size: 12px;
    line-height: normal;
    cursor: pointer;
}

/* ---------- the Businesses panel on a person ---------- */

/* "Shrink the text box and drop down and put the link button on the same row to
   the right." All three were free to take whatever width they liked, so the
   search box and the role dropdown filled the row between them and the button
   wrapped onto a line of its own. */
.affil-foot {
    padding: 12px 16px;
    border-top: 1px solid var(--line);
    background: #fafbfc;
}

.affil-link, .affil-new {
    display: flex; gap: 8px; align-items: center; margin: 0;
}

/* The search box takes what is left; everything else is told what it needs. */
.affil-link > :first-child { flex: 1 1 auto; min-width: 0; }
.affil-link select { flex: 0 0 148px; padding: 7px 10px; font-size: 12.5px; }
.affil-link .btn { flex: 0 0 auto; margin-left: auto; }

/* The create row, same shape: the name takes the slack and the rest is sized
   to its content — an ABN is eleven digits and never more. */
.affil-new { flex-wrap: wrap; }
.affil-new input, .affil-new select { padding: 7px 10px; font-size: 12.5px; }
.affil-new .affil-grow { flex: 1 1 200px; min-width: 0; }
.affil-new .affil-abn { flex: 0 0 130px; }
.affil-new select { flex: 0 0 148px; }
.affil-foot .field-hint { margin-top: 6px; }

/* Off the company altogether — an × against its name.

   It was a Remove in a fourth column, which took enough width from the first
   that "ZZ-TEST Colombo Earthworks Pty Ltd" wrapped to four lines. Beside the
   name it costs nothing, and it reads the way the × on a role chip does: that
   one takes off a capacity, this one takes off the company and every capacity
   with it.

   Always visible. It was faded in on hover, on the reasoning that a
   destructive control should not be the first thing the eye lands on — but a
   control you cannot see is one you cannot find, and the × on the role chips
   beside it has never hidden. Consistent with those is the point. */
/* Inline, not a flex row. As a flex container the name became an item that
   could shrink, and in a 155px cell it lost 32px to the × and wrapped
   "ZZ-TEST Colombo Landscaping" onto three lines instead of two. Inline, the
   × follows the last word and takes width only where there is some. */
.affil-name .affil-remove { display: inline; margin: 0; }

.affil-name .affil-remove button {
    background: none; border: none; cursor: pointer; color: var(--muted);
    font-size: 14px; line-height: 1; padding: 0 3px; border-radius: 999px;
    transition: color 120ms;
}

.affil-name .affil-remove button:hover { color: var(--bad); }

/* ---------- the notepad and the documents on a supplier ---------- */

/* "Make the other documents panel narrower, same width as businesses/282, and
   let Notepad take up the extra space."

   Measured there: 424px, with a drop zone 398 wide and 216 tall. Side by side
   as equal halves the supplier's came out at 466 and its drop zone was squashed
   to 65 — a strip rather than something to drop a pile onto.

   So the documents column is told what it is and the notepad takes the slack,
   and the two stretch to match so the dashed area fills its panel the way it
   does on a business. */
/* The panels, not every child.
 *
 * `> *` painted a <script> — documents/_slots ends by including the live-form
 * handler, so that script is a third child of this grid, and display:flex on it
 * beats the browser's own script { display: none }. Two hundred lines of
 * JavaScript rendered as prose down the middle of the page.
 *
 * The same trap sits in .trio-files below, where it has not fired only because
 * each of its children is a wrapping div. Both name .panel now. */
/* The cheat sheet: one rule to a row, with the date it was written.
 *
 * "Your cheat sheet, in your words, date-stamped every time you update it."
 *
 * The date carries weight rather than sitting in grey at the end, because it is
 * what the panel is for — a rule from March under a rule from August, and the
 * reader has to be able to tell at a glance which is which. Over a year old is
 * marked in the same amber a stale balance uses: not wrong, just worth checking
 * before it is quoted at a client.
 */
.policy-notes { max-height: 520px; overflow-y: auto; }
.policy-note { padding: 12px 16px; border-bottom: 1px solid #f0f2f3; }
.policy-note:last-child { border-bottom: none; }
.policy-note-head {
  display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap;
  margin-bottom: 5px; font-size: 12.5px;
}
.policy-note-head strong { font-size: 13px; color: var(--ink); }
.policy-note-when {
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.policy-note-when.stale { color: var(--warn); }
.policy-note-body { font-size: 13px; line-height: 1.6; white-space: pre-wrap; }

.pair-files { grid-template-columns: 1fr 424px; align-items: stretch; }
.pair-files > .panel { display: flex; flex-direction: column; flex: 1 1 auto; }
.pair-files > .panel > [x-show] { flex: 1 1 auto; display: flex; flex-direction: column; }
.pair-files .slots { flex: 1 1 auto; display: flex; flex-direction: column; }
.pair-files .slots > .drop-many {
    flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center;
    padding: 14px; min-height: 120px;
}

/* Enough height for the drop zone to be a target rather than a line. */
.pair-files > .panel { min-height: 260px; }

@media (max-width: 1200px) {
    .pair-files { grid-template-columns: 1fr; }
    .pair-files .slots > .drop-many { min-height: 90px; }
}

/* ---------- carrying a paid-out facility's asset across ---------- */

/* "On Edit add a bottom button, Add to unencumbered assets — on pressing it,
   additional fields for Value and Value date appear."

   Under the save row rather than in it: it is not part of saving the facility,
   it is a second thing he may want to do while he is here. */
.carry-over { border-top: 1px solid var(--line); padding: 10px 0 4px; margin-top: 4px; }

.carry-over-fields {
    display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin-top: 10px;
}
.carry-field { display: flex; flex-direction: column; gap: 3px; }
.carry-field > span { font-size: 11px; color: var(--muted); font-weight: 600; }
.carry-field input { padding: 6px 9px; font-size: 12.5px; width: 150px; }
.carry-over-fields > .meta { align-self: center; }

/* Who signs, in two bounded groups.

   "Guarantors of fucking what? All of a sudden it's now talking about the
   trust. There's no reference to the trust here at all." — the trustee, its
   directors and the guarantors ran together in one panel body, so the last
   heading read as belonging to the box above it.

   A rule and a small heading each, which is enough: the reader can see where
   one question stops and the next begins without a second panel's worth of
   chrome on a form he is filling in on a call. */
.structure-group + .structure-group { margin-top: 16px; }
.structure-group-head {
  font-size: 11.5px; font-weight: 700; color: var(--navy);
  letter-spacing: .3px; text-transform: none;
  padding-bottom: 6px; margin-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

/* Applications — new: the two columns that carry the names.

   Business leads, because it is what he looks down the list for, and it is
   given enough room that a trust name does not wrap on to a second line and set
   the height of every row. Asset follows with rather less, since it is a make
   and model rather than a legal name.

   Percentages, not pixels: the table already scrolls inside itself, and a fixed
   width would either waste a wide screen or force the scroll on a laptop. */
.col-business { width: 26%; min-width: 240px; }
.col-asset { width: 18%; min-width: 150px; }

/* ---------------------------------------------------------------------------
   Assets a live facility is held against.

   "Asset value is shown on Foxy but no assets are listed."

   They sit in the same table as the ones owned outright, because to him they
   are all things the client has — what differs is that the record of the thing
   lives on the loan. Marked, not hidden: a lender reading the panel should be
   able to tell which of these is encumbered, and the row says so by naming the
   facility that holds it.

   Distinct from .al-financed, which marks a liability written by a settled
   deal. Neither name is free to move without checking the other.
   --------------------------------------------------------------------------- */
.al-from-facility td { background: #fbfcfd; }
.al-from-facility-type { color: var(--muted); }

/* which loan holds it — quiet, because the thing itself is what he is reading */
.al-held-by { color: var(--muted); font-size: 11.5px; white-space: nowrap; }


/* The two things an application asks of a person, on the row it asks about.

   "Email is never asked for during the new-application flow — he has to leave
   and go to the person's record." Laid out like the add-a-role box beside it,
   because it opens the same way and from the same place. */

                   padding: 6px 0 8px 26px; }
.ptree-detail { display: inline-flex; flex-direction: column; gap: 2px; margin-right: 10px; }
.ptree-detail > span { font-size: 11px; color: var(--muted); }
.ptree-detail input { font-size: 12.5px; padding: 4px 6px; }

/* "Bring it across", moved out of the notice at the top and put under the
   structure it rewrites — quiet, because it changes a submitted application and
   read as an invitation to do so while it was a navy button above the fold. */
.drift-foot { margin: 0; }
