/* PFG ABL Deal Platform — design language.
 *
 * Tokens and components carried across from the v1 demo, which HANDOVER.md §6
 * defines as the spec. The rules, restated so they are not lost:
 *   Jost everywhere. Square corners (2px). Hairline taupe borders, no heavy
 *   shadows, no gradients, no pills, no emoji. NO GREEN — positive states are
 *   slate. No stoplight red/green. Orange on at most one or two small things
 *   per screen, never as a fill or large area. Eyebrow labels are ALL CAPS,
 *   letter-spaced, slate.
 */

@font-face {
  font-family: 'Jost';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/jost.928f4210aa48.woff2") format('woff2');
}

:root {
  --linen: #EFEDEA;
  --white: #FFFFFF;
  --charcoal: #333333;
  --slate: #4D6E82;
  --slate-dark: #3E5A6B;
  --accent-soft: #96B0BD;
  --accent-faint: #CDD9DF;
  --stone: #7E7F7F;
  --taupe: #D9D1CC;
  --taupe-15: #F5F2F0;
  --taupe-25: #EFEAE6;
  --pop: #FF8A00;
  /* Search highlighting only. Yellow is not otherwise in this palette, and Rene
     asked for it by name: "it needs like a yellow highlight". The no-fills rule
     governs STATUS colour — a found word is not a status, it is the thing being
     looked for, and every search box anyone has used marks it this way. */
  --find: #FFE9A3;
  --find-strong: #FFD447;
  --error: #B5443A;
  --font: 'Jost', 'GT Walsheim', 'Century Gothic', 'Avenir Next', Futura, Arial, sans-serif;
  --r: 2px;
  --ease: cubic-bezier(.4, 0, .2, 1);
  /* Overshoots and settles — the spring the deal-agent panel rises on. The control
     value above 1 is the overshoot; keep it under ~1.6 or it reads as a toy. */
  --spring-up: cubic-bezier(.34, 1.56, .64, 1);
  /* Drops away with a touch of anticipation. Deliberately faster than the rise:
     leaving should not cost as much time as arriving. */
  --spring-down: cubic-bezier(.5, -.4, .85, .3);
  --shadow: 0 1px 3px rgba(51, 51, 51, .06), 0 4px 14px rgba(51, 51, 51, .05);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  background: var(--linen);
  color: var(--charcoal);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 { font-weight: 500; line-height: 1.15; }
button { font-family: inherit; font-size: inherit; cursor: pointer; }
a { color: var(--slate); text-decoration: none; }
a:hover { color: var(--slate-dark); }
::selection { background: var(--accent-faint); }

/* ---------- shell ---------- */
#shell { display: flex; min-height: 100vh; }
aside {
  width: 232px; flex-shrink: 0; background: var(--white);
  border-right: 1px solid var(--taupe); display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
}
.logo-wrap { padding: 26px 22px 18px; border-bottom: 1px solid var(--taupe); }
.logo-wrap svg { width: 150px; height: auto; display: block; }
.logo-sub {
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--stone); margin-top: 10px; font-weight: 500;
}
nav { padding: 18px 12px; flex: 1; }
.nav-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  background: none; border: none; border-radius: var(--r); padding: 9px 12px;
  color: var(--charcoal); font-weight: 400; font-size: 14.5px; margin-bottom: 2px;
  transition: background .15s var(--ease);
}
.nav-item:hover { background: var(--taupe-15); color: var(--charcoal); }
.nav-item.active { background: var(--slate); color: #fff; font-weight: 500; }
.nav-item .badge-count {
  margin-left: auto; background: var(--pop); color: #fff; font-size: 11px;
  font-weight: 600; min-width: 19px; height: 19px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center; padding: 0 6px;
}
.nav-item.active .badge-count { background: #fff; color: var(--slate); }
.nav-sep { border: none; border-top: 1px solid var(--taupe); margin: 14px 6px; }
.nav-label {
  font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--stone); padding: 2px 12px 8px; font-weight: 500;
}
.user-chip {
  padding: 16px 22px; border-top: 1px solid var(--taupe); display: flex;
  align-items: center; gap: 10px; font-size: 13px; color: var(--stone);
}
.user-chip form { margin-left: auto; }
.avatar {
  width: 30px; height: 30px; border-radius: 50%; background: var(--slate);
  color: #fff; display: inline-flex; align-items: center; justify-content: center;
  font-size: 11.5px; font-weight: 500; flex-shrink: 0;
}
.avatar.soft { background: var(--accent-soft); }
.avatar.agent { background: var(--charcoal); }
.avatar.sys { background: var(--taupe); color: var(--charcoal); font-size: 8.5px; }
.avatar.sm { width: 24px; height: 24px; font-size: 10px; }
/* 1240 was leaving a 475px dead strip down the right of a 1900px window — the "unused
   space" complaint, and it was the page cap, not the layouts inside it. The cap now sits
   high enough to fill a normal wide monitor and low enough that body text on a 4K screen
   does not run to 3000px. */
main { flex: 1; min-width: 0; padding: 34px 44px 44px; max-width: 1760px; }
/* A dashboard uses the whole window. See the note in base.html. */
main.wide { max-width: none; padding: 28px 28px 28px; }

/* Push notifications.
 *
 * Bottom-right, stacked, one hairline card each. Orange only on the left edge — the design
 * language allows the accent on one or two small things per screen and never as a fill, and
 * a toast that arrives uninvited is the last thing that should shout. */
.toasts {
  position: fixed; right: 20px; bottom: 20px; z-index: 200;
  display: flex; flex-direction: column; gap: 10px; max-width: 340px;
}
.toast {
  position: relative; background: var(--white); border: 1px solid var(--taupe);
  border-left: 2px solid var(--pop); border-radius: var(--r);
  padding: 14px 34px 14px 16px; box-shadow: var(--shadow);
  animation: toast-in .18s var(--ease);
}
.toast.going { opacity: 0; transform: translateY(4px); transition: opacity .5s, transform .5s; }
.toast-title { font-size: 13.5px; font-weight: 500; line-height: 1.35; }
.toast-body { font-size: 12.5px; color: var(--stone); margin-top: 4px; line-height: 1.45; }
.toast-open { display: inline-block; font-size: 12.5px; font-weight: 500; margin-top: 8px; }
.toast-close {
  position: absolute; top: 8px; right: 8px; background: none; border: none;
  color: var(--stone); font-size: 16px; line-height: 1; padding: 2px 5px;
}
.toast-close:hover { color: var(--charcoal); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }

@media (max-width: 620px) {
  .toasts { left: 16px; right: 16px; max-width: none; }
}

/* The portal's own notifications link, matching the internal nav's badge. */
.pt-bell {
  display: inline-flex; align-items: center; gap: 8px; font-size: 14px;
  color: var(--charcoal); font-weight: 500;
}
.pt-bell:hover { color: var(--slate); }
.pt-bell .badge-count {
  background: var(--pop); color: #fff; font-size: 11px; font-weight: 600;
  min-width: 19px; height: 19px; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center; padding: 0 6px;
}

/* ---------- common ---------- */
.eyebrow {
  font-size: 11.5px; letter-spacing: .18em; text-transform: uppercase;
  font-weight: 500; color: var(--slate);
}
.eyebrow.pop { color: var(--pop); }
.view-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; margin-bottom: 28px;
}
.view-head h1 { font-size: 32px; margin-top: 6px; }
.view-head .sub { color: var(--stone); font-size: 14px; margin-top: 6px; max-width: 640px; }
.card { background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r); }
.btn {
  display: inline-flex; align-items: center; gap: 8px; border-radius: var(--r);
  padding: 9px 18px; font-weight: 500; font-size: 14px; border: 1px solid transparent;
  transition: background .15s var(--ease); text-decoration: none;
}
.btn-primary { background: var(--slate); color: #fff; }
.btn-primary:hover { background: var(--slate-dark); color: #fff; }
.btn-secondary { background: var(--white); border-color: var(--taupe); color: var(--charcoal); }
.btn-secondary:hover { background: var(--taupe-15); color: var(--charcoal); }
.btn-ghost { background: none; border: none; color: var(--slate); font-weight: 500; padding: 6px 8px; }
.btn-danger { background: var(--white); border-color: var(--taupe); color: var(--error); }
.btn-danger:hover { background: #F8F0EF; }
.btn.sm { padding: 6px 13px; font-size: 13px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px;
  font-weight: 500; letter-spacing: .04em; padding: 3px 10px; border-radius: var(--r);
  border: 1px solid var(--taupe); background: var(--taupe-15); color: var(--charcoal);
  white-space: nowrap;
}
.chip.slate { background: var(--accent-faint); border-color: var(--accent-faint); color: var(--charcoal); }
.chip.deep { background: var(--slate); border-color: var(--slate); color: #fff; }
.chip.charcoal { background: var(--charcoal); border-color: var(--charcoal); color: #fff; }
.chip.pop { background: #fff; border-color: var(--pop); color: var(--pop); }
.chip.err { background: #fff; border-color: var(--error); color: var(--error); }
.chip.ghost { background: #fff; }
.muted { color: var(--stone); }
.small { font-size: 13px; }
.tiny { font-size: 12px; }
.num { font-variant-numeric: tabular-nums; }

/* stat row */
.stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--taupe); border: 1px solid var(--taupe); border-radius: var(--r);
  overflow: hidden; margin-bottom: 24px;
}
.stat { background: var(--white); padding: 16px 20px; }
.stat .v { font-size: 28px; font-weight: 500; line-height: 1.05; font-variant-numeric: tabular-nums; }
.stat .v .unit { font-size: 18px; color: var(--stone); font-weight: 400; }
.stat .l {
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--stone); margin-top: 6px; font-weight: 500;
}
.stat.pop .v { color: var(--pop); }

/* controls */
.controls { display: flex; align-items: center; gap: 12px; margin-bottom: 22px; flex-wrap: wrap; }
.controls input[type=search], .controls select {
  font-family: inherit; font-size: 14px; padding: 8px 12px;
  border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal); outline: none;
}
.controls input[type=search] { width: 260px; }
.controls input[type=search]:focus, .controls select:focus { border-color: var(--slate); }
.seg {
  display: inline-flex; border: 1px solid var(--taupe); border-radius: var(--r);
  overflow: hidden; margin-left: auto;
}
.seg a, .seg button {
  background: var(--white); border: none; padding: 8px 16px; font-size: 13.5px;
  color: var(--stone); font-weight: 500; text-decoration: none;
}
.seg a.on, .seg button.on { background: var(--charcoal); color: #fff; }

/* deal cards */
/* 265, not 330: the page gives the grid 1144px, and four columns need the minimum at or
   under 275. At 330 it silently fell back to three and left 120px dead at the right. */
.deal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(265px, 1fr)); gap: 14px; }
.deal-card {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 17px 19px; display: block; color: inherit;
  transition: box-shadow .18s var(--ease), transform .18s var(--ease);
}
.deal-card:hover { box-shadow: var(--shadow); transform: translateY(-1px); color: inherit; }
.deal-card .top { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 2px; }
.deal-card h3 { font-size: 17px; font-weight: 500; }
.deal-card .co { color: var(--stone); font-size: 12.5px; margin-bottom: 11px; }
.meta-row { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 13px; }
.pbar { height: 5px; background: var(--taupe-25); border-radius: 2px; overflow: hidden; margin: 6px 0; }
.pbar > i { display: block; height: 100%; background: var(--slate); border-radius: 2px; }
.deal-card .phase-line { display: flex; justify-content: space-between; font-size: 12.5px; color: var(--stone); }
.deal-card .foot {
  display: flex; align-items: center; justify-content: space-between; margin-top: 14px;
  padding-top: 13px; border-top: 1px solid var(--taupe-25); font-size: 12.5px; color: var(--stone);
}
.days-warn { color: var(--pop); font-weight: 500; }

/* table */
table.data {
  width: 100%; border-collapse: collapse; background: var(--white);
  border: 1px solid var(--taupe); border-radius: var(--r); font-size: 14px;
}
table.data th {
  background: var(--charcoal); color: #fff; text-align: left; font-weight: 500;
  font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  padding: 0; white-space: nowrap;
}
table.data th a, table.data th span {
  display: block; padding: 11px 16px; color: #fff;
}
table.data th a:hover { background: #404040; color: #fff; }
table.data td { padding: 12px 16px; border-top: 1px solid var(--taupe-25); vertical-align: middle; }
table.data tbody tr { transition: background .12s var(--ease); }
table.data tbody tr:nth-child(even) { background: var(--linen); }
table.data tbody tr:hover, table.data tbody tr:nth-child(even):hover { background: var(--taupe-15); }
table.data td a { color: inherit; display: block; }
.tbl-wrap { overflow-x: auto; }

/* deal detail */
.back {
  display: inline-flex; align-items: center; gap: 6px; color: var(--slate);
  font-weight: 500; font-size: 13.5px; background: none; border: none; margin-bottom: 18px;
}
/* Not space-between: with the page cap raised, that threw the date box against the right
   edge and opened a 600px hole in the middle of the header. The dates sit beside the
   heading instead, and the row ends where its content ends. */
.deal-head {
  display: flex; justify-content: flex-start; gap: 44px;
  align-items: flex-start; margin-bottom: 20px; flex-wrap: wrap;
}
.deal-head > div:first-child { flex: 1 1 520px; max-width: 900px; }
.deal-head h1 { font-size: 30px; margin: 4px 0 6px; }
.deal-head .facts { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.dates-grid {
  display: grid; grid-template-columns: repeat(4, minmax(96px, 1fr)); gap: 1px;
  background: var(--taupe); border: 1px solid var(--taupe); border-radius: var(--r);
  overflow: hidden; min-width: 400px;
}
.dates-grid > div { background: var(--white); padding: 10px 13px; }
.dates-grid .dl {
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--stone); font-weight: 500;
}
.dates-grid .dv { font-size: 14px; font-weight: 500; margin-top: 3px; font-variant-numeric: tabular-nums; }
/* THE RAIL IS GONE. Rene: "look at the stuff at the right. It is way too much and it
   leaves a mess of empty space below the stages."

   A rail's height is independent of the column beside it, so the two can never agree —
   the task list is as long as one stage's tasks and the rail is as long as whatever is
   in it. The Layout note in CLAUDE.md is about the same failure in 2026, fixed then by
   moving reference cards into a band; adding cards back to the rail brought it straight
   back. Work runs full width now, reference wraps underneath in the band.

   `.detail-cols` is kept because other templates use it. */
.detail-cols { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 22px; align-items: start; }
.stage-work { margin-bottom: 18px; }

/* phase stepper */
/* THE STAGE SELECTOR. Rene: "make them less tall, more horizontal", and "just enable
   the ones above as buttons".

   They were 24px numerals stacked over a wrapped name over a count, with a 32px
   min-height holding the box open for names that did not need it — four rows of air
   across the full width. Now one row each: number, name, progress. A third the height,
   and the whole thing reads left to right like the process it describes. */
.stepper { display: grid; grid-template-columns: repeat(5, 1fr); gap: 16px; margin-bottom: 16px; }
.step {
  display: flex; align-items: baseline; gap: 8px;
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 9px 12px; position: relative; text-decoration: none; color: var(--charcoal);
  transition: border-color .12s var(--ease);
}
.step:hover { border-color: var(--slate); }
.step:focus-visible { outline: 2px solid var(--slate); outline-offset: 2px; }
.step .sn { font-size: 13px; font-weight: 500; color: var(--stone); line-height: 1; font-variant-numeric: tabular-nums; }
.step .st {
  font-size: 12px; font-weight: 500; line-height: 1.3; flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.step .sc { font-size: 11.5px; color: var(--stone); font-variant-numeric: tabular-nums; }
.step.done .sn { color: var(--accent-soft); }
/* CURRENT is where the deal is; ON is what you are looking at. They are usually the same
   and must not be drawn the same, or clicking through stages looks like it moved the
   deal. Current is a rule underneath; the one being read is filled. */
.step.current { border-color: var(--slate); }
.step.current .sn { color: var(--slate); }
.step.current::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 3px;
  background: var(--slate);
}
.step.done::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 3px;
  background: var(--accent-soft);
}
.step.on {
  background: var(--slate); border-color: var(--slate); color: var(--white);
}
.step.on .sn, .step.on .sc { color: var(--accent-faint); }

/* The panels the stepper switches between. `hidden` is the whole mechanism, so it gets
   its own rule: any author `display` here would beat the browser's built-in
   `[hidden] { display: none }` and every stage would render at once. That is not
   hypothetical — it is how the deal agent's panel came to open itself on every page. */
.stage-panel[hidden] { display: none !important; }

/* tasks */
.phase-block {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  margin-bottom: 14px; overflow: hidden;
}
.phase-block > summary {
  display: flex; align-items: center; gap: 14px; padding: 14px 20px;
  cursor: pointer; user-select: none; list-style: none;
}
.phase-block > summary::-webkit-details-marker { display: none; }
.phase-block > summary:hover { background: var(--taupe-15); }
.phase-block h3 { font-size: 15.5px; font-weight: 500; flex: 1; }
.phase-block .ph-num { font-size: 20px; color: var(--taupe); font-weight: 500; font-variant-numeric: tabular-nums; }
.phase-block.current .ph-num { color: var(--slate); }
.caret { transition: transform .2s var(--ease); color: var(--stone); font-size: 12px; }
.phase-block[open] .caret { transform: rotate(90deg); }
.task-list { border-top: 1px solid var(--taupe-25); }
.task {
  display: flex; align-items: center; gap: 12px; padding: 10px 20px;
  border-bottom: 1px solid var(--taupe-25); font-size: 14px;
}
.task:last-child { border-bottom: none; }
.task:hover { background: var(--taupe-15); }
.task form { display: flex; align-items: center; }
.tick {
  width: 18px; height: 18px; border: 1.5px solid var(--taupe); border-radius: var(--r);
  background: #fff; flex-shrink: 0; display: inline-flex; align-items: center;
  justify-content: center; cursor: pointer; transition: all .12s var(--ease);
  color: transparent; font-size: 11px; padding: 0;
}
.tick:hover { border-color: var(--slate); }
.task.done .tick { background: var(--slate); border-color: var(--slate); color: #fff; }
.task.done .tt { color: var(--stone); text-decoration: line-through; text-decoration-color: var(--taupe); }
.task .tt { flex: 1; }
.task .twho { font-size: 12px; color: var(--stone); white-space: nowrap; }
.task .overdue { color: var(--pop); font-weight: 500; font-size: 12px; }

/* System-verified tasks: completion is computed, so the tick is an indicator
   rather than a control. Kept visually quiet — a checklist where a third of the
   rows shouted would be worse than the problem it solves. */
.task.verified .tick { border-style: dashed; cursor: default; }
.task.verified.done .tick { border-style: solid; }
.task .auto-note {
  display: block; font-size: 11.5px; color: var(--stone); margin-top: 2px;
}
.task.done .auto-note { color: var(--accent-soft); }
.task .tt { line-height: 1.35; }

/* right rail */
.rail-card {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 15px 17px; margin-bottom: 12px;
}
.rail-card h4 {
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stone); font-weight: 500; margin-bottom: 12px;
}
.gate-rec {
  border: 1px solid var(--taupe); border-radius: var(--r); padding: 12px 14px;
  margin-bottom: 10px; background: var(--taupe-15);
}
.gate-rec .gd { font-weight: 500; font-size: 14px; }
.gate-rec .gm { font-size: 12.5px; color: var(--stone); margin-top: 2px; }
.gate-rec.superseded { opacity: .6; }
.kv {
  display: flex; justify-content: space-between; gap: 12px; font-size: 13.5px;
  padding: 5px 0; border-bottom: 1px solid var(--taupe-25);
}
.kv:last-child { border-bottom: none; }
.kv b { font-weight: 500; font-variant-numeric: tabular-nums; }
.lock-note {
  font-size: 12px; color: var(--stone); margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--taupe-25);
}

/* A button that is working. The action behind "Suggest from data room" takes tens of
   seconds, and a form with no feedback reads as a hung page. See static/js/working.js. */
.btn.is-working { opacity: .75; cursor: progress; }
.btn.is-working::before {
  content: ""; display: inline-block; width: 10px; height: 10px; margin-right: 7px;
  border: 1.5px solid var(--taupe); border-top-color: var(--slate);
  border-radius: 50%; vertical-align: -1px;
  animation: pfg-spin .7s linear infinite;
}
@keyframes pfg-spin { to { transform: rotate(360deg); } }
/* Somebody who has asked not to see motion gets the label change and no spin. */
@media (prefers-reduced-motion: reduce) {
  .btn.is-working::before,
  a.is-working::after { animation: none; }
  /* Still visible, still says "working" — a solid bar rather than a moving one. */
  #pfg-progress::before { animation: none; width: 100%; }
}
.working-note {
  font-size: 12px; color: var(--stone); margin-top: 6px; max-width: 260px;
}

/* A link that has been clicked and is fetching a slow page. Dimmed and inert, because a
   link that looks unchanged is one somebody clicks a second time. */
a.is-working {
  opacity: .55; cursor: progress; pointer-events: none;
}
a.is-working::after {
  content: ""; display: inline-block; width: 9px; height: 9px; margin-left: 7px;
  border: 1.5px solid var(--taupe); border-top-color: var(--slate);
  border-radius: 50%; vertical-align: -1px;
  animation: pfg-spin .7s linear infinite;
}

/* The page-level cue: a hairline bar across the top, for anything slow enough that the
   control alone is not enough — and for a LINK, where the click navigates away and the
   control's own cue goes with it.

   Slate, not orange: the design language keeps orange for one or two small things per
   screen, and a bar across the whole width is neither small nor rare. */
#pfg-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 9999;
  background: var(--taupe-25); overflow: hidden;
}
#pfg-progress::before {
  content: ""; position: absolute; top: 0; left: 0; height: 100%; width: 40%;
  background: var(--slate);
  animation: pfg-progress-slide 1.1s ease-in-out infinite;
}
@keyframes pfg-progress-slide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

/* "Soon" — a not-yet-active affordance. Hairline, muted, no fill, per the design
   language: it should read as "coming", not as a live status badge. */
.tag-soon {
  display: inline-block; margin-left: 6px; padding: 1px 6px;
  font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--stone); border: 1px solid var(--taupe); border-radius: var(--r);
  vertical-align: middle;
}

/* activity */
.feed { background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r); }
.evt {
  display: flex; gap: 14px; padding: 14px 22px;
  border-bottom: 1px solid var(--taupe-25); align-items: flex-start;
}
.evt:last-child { border-bottom: none; }
.evt .etxt { flex: 1; font-size: 14px; }
.evt .etxt b { font-weight: 500; }
.evt .emeta { font-size: 12px; color: var(--stone); margin-top: 1px; }
.evt .etime { font-size: 12px; color: var(--stone); white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ---------- Q&A ---------- */
.qa-section { margin-bottom: 26px; }
.qa-section > h3 {
  font-size: 15px; font-weight: 500; margin-bottom: 10px;
  display: flex; align-items: baseline; gap: 10px;
}
.qa-section > h3 .snum { color: var(--accent-soft); font-size: 20px; font-weight: 500; }
.q-row {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  margin-bottom: 8px; overflow: hidden;
  /* Answering a question returns you to it by anchor. Without this the row sits
     jammed against the top of the viewport with no context above it. */
  scroll-margin-top: 20px;
}
/* Briefly mark the question you just came back to, so it is obvious which one
   was saved when you are working down a long list. */
.q-row:target { border-color: var(--slate); box-shadow: 0 0 0 1px var(--slate); }
.q-row > header { display: flex; align-items: center; gap: 14px; padding: 12px 18px; cursor: pointer; }
.q-row > header:hover { background: var(--taupe-15); }
.qnum {
  font-weight: 500; color: var(--slate); font-variant-numeric: tabular-nums;
  white-space: nowrap; font-size: 14px; min-width: 44px;
}
.qtext { flex: 1; font-size: 14px; }
.q-body {
  border-top: 1px solid var(--taupe-25); padding: 16px 18px 18px;
  display: none; background: var(--taupe-15);
}
.q-row.open .q-body { display: block; }
.q-meta-line {
  display: flex; gap: 18px; font-size: 12.5px; color: var(--stone);
  margin-bottom: 14px; flex-wrap: wrap;
}
.msg {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 12px 16px; margin-bottom: 8px; font-size: 14px;
}
.msg .mh { display: flex; justify-content: space-between; font-size: 12px; color: var(--stone); margin-bottom: 5px; }
.msg .mh b { color: var(--charcoal); font-weight: 500; }
/* Internal-only notes are visually loud on purpose: the deal team responded to
   seeing the safety property, not just being told about it. */
.msg.internal { background: var(--taupe-25); border-style: dashed; }
.msg.internal .int-flag {
  color: var(--pop); font-weight: 600; font-size: 10.5px;
  letter-spacing: .12em; text-transform: uppercase;
}
.q-src {
  font-size: 12.5px; color: var(--stone); border-left: 2px solid var(--accent-soft);
  padding-left: 10px; margin-bottom: 12px;
}

/* ---------- card-with-payload (invitations, Affinity records) ---------- */
.appr-card {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 20px 22px; margin-bottom: 14px;
}
.appr-card .ah { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.appr-card .ah .spacer { flex: 1; }
.payload {
  background: var(--taupe-15); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 14px 18px; font-size: 14px; margin-bottom: 14px; white-space: pre-wrap;
}
.payload .flag { background: #FFF3E4; border-bottom: 2px solid var(--pop); padding: 0 3px; }
.payload .subj { font-weight: 500; margin-bottom: 8px; }
.appr-foot { display: flex; gap: 8px; align-items: center; }
.appr-foot .meta { margin-left: auto; font-size: 12px; color: var(--stone); }

/* ---------- borrower portal: a separate surface ---------- */
/* Wider than the demo's 960px column, which left a wide window looking mostly
   empty. Matches the internal shell's cap so the two surfaces feel related
   without looking identical. */
.portal-top { background: var(--white); border-bottom: 1px solid var(--taupe); }
.portal-top .inner {
  max-width: 1760px; margin: 0 auto; padding: 16px 32px;
  display: flex; align-items: center; gap: 20px;
}
/* Without this the inline wordmark renders at its intrinsic size. */
.portal-top svg { width: 130px; height: auto; flex-shrink: 0; }
.portal-top .pt-label {
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--stone); font-weight: 500;
  border-left: 1px solid var(--taupe); padding-left: 20px;
}
.portal-body { max-width: 1760px; margin: 0 auto; padding: 28px 32px 56px; }

/* Portal head: tighter than the internal view-head, and the summary sits on the
   same line as the greeting rather than stacking. */
.portal-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; flex-wrap: wrap; margin-bottom: 22px;
}
.portal-head h1 { font-size: 28px; margin-top: 4px; }
.portal-head .sub { color: var(--stone); font-size: 13.5px; margin-top: 4px; max-width: 620px; }
.portal-head .tally { display: flex; gap: 8px; flex-wrap: wrap; }

/* auto-FIT, not auto-fill: with one deal the card stretches to fill the row
   instead of sitting narrow against dead space. */
.portal-deals {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 14px; align-items: start;
}

/* One card per piece of work, so nothing important sits alongside something
   unrelated. The transaction and its progress on top; Questions, Data tapes and
   Documents each in their own card underneath. */
.deal-block { margin-bottom: 28px; }
.deal-context .next-step { margin-top: 14px; font-weight: 500; }
.task-cards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px; margin-top: 12px;
}
.task-card { display: flex; flex-direction: column; }
.task-card h4 {
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stone); font-weight: 500;
}
.task-card .task-count {
  font-size: 30px; font-weight: 500; line-height: 1.05; margin: 10px 0 2px;
  font-variant-numeric: tabular-nums;
}
.task-card .task-count.pop { color: var(--pop); }
.task-card .task-count.muted { color: var(--taupe); }
.task-card p { margin-bottom: 14px; }
.task-card .btn { margin-top: auto; align-self: flex-start; }
/* A card that needs the borrower to act carries the one accent on the screen. */
.task-card.needs-you { border-color: var(--pop); }
.task-card.coming { background: var(--taupe-15); }
.portal-card {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 18px 20px;
}
.portal-card h3 { font-size: 17.5px; font-weight: 500; }
.portal-card .co { color: var(--stone); font-size: 13px; margin-bottom: 12px; }
.portal-card .foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--taupe-25);
  flex-wrap: wrap;
}
/* Borrower stage strip.
 *
 * Each stage states its own condition in words. Shade alone was ambiguous: a darker
 * bar reads as "completed" to most people, so making CURRENT the darkest made the
 * current stage look finished and the whole strip look out of order.
 *
 * Completed stages carry a tick, upcoming ones carry their step number, so the
 * sequence is unmistakable without reading any colour at all.
 *
 * No green and no red: a borrower reading a stoplight would infer a judgement the
 * platform is not making about their transaction.
 */
.stage-strip {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 10px; margin-top: 16px;
}
.stage-strip .ss-bar {
  display: block; height: 4px; border-radius: 2px; background: var(--taupe-25);
}
.stage-strip .ss-step {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%; margin-top: 8px;
  font-size: 10px; font-weight: 600; font-variant-numeric: tabular-nums;
  background: var(--taupe-25); color: var(--stone);
}
.stage-strip .ss-label {
  display: block; font-size: 11.5px; line-height: 1.3; color: var(--stone); margin-top: 5px;
}
.stage-strip .ss-state {
  display: block; font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--stone); margin-top: 3px;
}

/* Complete: filled, ticked, and said so. */
.stage-strip .ss.done .ss-bar { background: var(--accent-soft); }
.stage-strip .ss.done .ss-step { background: var(--accent-soft); color: #fff; }
.stage-strip .ss.done .ss-label { color: var(--charcoal); }

/* In progress: the one stage that is emphasised, and labelled as underway rather
   than left to be inferred from a colour. */
.stage-strip .ss.current .ss-bar { background: var(--slate); }
.stage-strip .ss.current .ss-step { background: var(--slate); color: #fff; }
.stage-strip .ss.current .ss-label { color: var(--charcoal); font-weight: 500; }
.stage-strip .ss.current .ss-state { color: var(--slate); font-weight: 600; }

/* Not started: quiet, and explicitly quiet. */
.stage-strip .ss.ahead .ss-label,
.stage-strip .ss.ahead .ss-state { color: var(--taupe); }

@media (max-width: 760px) {
  /* Five columns on a phone is unreadable; stack them. */
  .stage-strip { grid-auto-flow: row; gap: 8px; }
  .stage-strip .ss { display: grid; grid-template-columns: 16px 1fr auto; gap: 8px; align-items: center; }
  .stage-strip .ss-bar { grid-column: 1 / -1; }
  .stage-strip .ss-step, .stage-strip .ss-label, .stage-strip .ss-state { margin-top: 0; }
}

.portal-note {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 16px 20px; margin-top: 14px;
}
.portal-note h4 {
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stone); font-weight: 500; margin-bottom: 8px;
}
.portal-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--taupe); margin: 22px 0 26px; }
.portal-tabs button {
  background: none; border: none; padding: 10px 18px; font-size: 14.5px;
  color: var(--stone); font-weight: 500; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.portal-tabs button.on { color: var(--charcoal); border-bottom-color: var(--slate); }
.portal-progress { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 8px; }
.answer-box {
  width: 100%; font-family: inherit; font-size: 14px; border: 1px solid var(--taupe);
  border-radius: var(--r); padding: 10px 12px; min-height: 74px; resize: vertical;
  outline: none; background: #fff;
}
.answer-box:focus { border-color: var(--slate); }
.upload-btn {
  border: 1px dashed var(--slate); background: #fff; color: var(--slate);
  border-radius: var(--r); padding: 6px 14px; font-size: 13px; font-weight: 500;
}
.upload-btn:hover { background: var(--taupe-15); }

/* ---------- tape column mapping ---------- */
.map-form { max-width: 820px; }
.map-group { margin-bottom: 26px; }
.map-group > h4 {
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stone); font-weight: 500; margin-bottom: 12px;
  padding-bottom: 8px; border-bottom: 1px solid var(--taupe);
}
.map-group > h4 .req { color: var(--pop); letter-spacing: .1em; }
.map-row {
  display: grid; grid-template-columns: minmax(0, 1fr) 260px auto; gap: 14px;
  align-items: start; padding: 9px 0; border-bottom: 1px solid var(--taupe-25);
}
.map-row:last-child { border-bottom: none; }
.map-row label { font-size: 14px; }
.map-row label .hint {
  display: block; font-size: 12px; color: var(--stone); margin-top: 2px;
}
.map-row select {
  font-family: inherit; font-size: 13.5px; padding: 7px 10px; width: 100%;
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  color: var(--charcoal); outline: none;
}
.map-row select:focus { border-color: var(--slate); }
/* A guess is flagged so nobody mistakes it for a decision the borrower made. */
.map-row .guessed {
  font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--pop); white-space: nowrap; padding-top: 9px;
}
.extra-cols { display: flex; flex-wrap: wrap; gap: 6px; }
.extra-col {
  display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
  border: 1px solid var(--taupe); border-radius: var(--r); padding: 5px 10px;
  background: var(--white); cursor: pointer;
}
.extra-col:hover { background: var(--taupe-15); }

/* The embedded analyzer dashboard. */
.analyzer-frame {
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  overflow: hidden;
}
.analyzer-frame iframe { display: block; width: 100%; height: 78vh; border: 0; }

/* The tape analysis, framed on a platform page. Taller than the generic frame above,
   because a dashboard of strats and vintages is the whole point of the screen rather than
   a panel on it — and the platform's own header stays visible above it, which is what
   makes it read as being here rather than somewhere else. */
.analysis-frame {
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  overflow: hidden;
}
.analysis-frame iframe {
  display: block; width: 100%; height: calc(100vh - 190px); min-height: 620px; border: 0;
}

@media (max-width: 760px) {
  .map-row { grid-template-columns: 1fr; gap: 6px; }
  .map-row .guessed { padding-top: 0; }
}

/* forms */
.form-grid { display: grid; gap: 16px; max-width: 560px; }
.field label {
  display: block; font-size: 11.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--stone); font-weight: 500; margin-bottom: 5px;
}
.field input, .field select, .field textarea {
  width: 100%; font-family: inherit; font-size: 14px; padding: 9px 12px;
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  color: var(--charcoal); outline: none;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--slate); }
.field textarea { min-height: 90px; resize: vertical; }
.field .help { font-size: 12px; color: var(--stone); margin-top: 4px; }
.field .errors { font-size: 12.5px; color: var(--error); margin-top: 4px; }
.field select[multiple] { min-height: 110px; }
.form-actions { display: flex; gap: 8px; align-items: center; margin-top: 8px; }

/* combobox — a dropdown that opens on click and narrows as you type.
   Built by static/js/combobox.js over any input with a `list`. Styled to sit in the
   same square, hairline language as a plain field: it should read as the field, opened,
   not as a widget bolted onto it. */
.combo { position: relative; }
.combo-caret {
  position: absolute; top: 0; right: 0; height: 100%; width: 30px;
  display: flex; align-items: center; justify-content: center;
  border: none; background: none; cursor: pointer; padding: 0;
  color: var(--stone); font-family: inherit; font-size: 11px; line-height: 1;
}
.combo-caret:hover { color: var(--charcoal); }
.field .combo-input { padding-right: 32px; }
.combo-list {
  position: absolute; z-index: 40; top: calc(100% + 2px); left: 0; right: 0;
  max-height: 260px; overflow-y: auto; margin: 0; padding: 0; list-style: none;
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  /* The one shadow in the design language that earns itself: this floats over content
     and needs to read as above the page rather than cut into it. */
  box-shadow: var(--shadow);
}
.combo-option {
  padding: 8px 12px; font-size: 14px; color: var(--charcoal); cursor: pointer;
  border-top: 1px solid var(--taupe-25);
}
.combo-option:first-child { border-top: none; }
.combo-option:hover, .combo-option.is-active { background: var(--taupe-15); }
.combo-empty { padding: 8px 12px; font-size: 12.5px; color: var(--stone); }

/* messages */
.messages { position: fixed; bottom: 28px; left: 50%; transform: translateX(-50%); z-index: 99; }
.messages li {
  list-style: none; background: var(--charcoal); color: #fff; padding: 11px 22px;
  border-radius: var(--r); font-size: 14px; max-width: 520px; box-shadow: var(--shadow);
  margin-top: 8px;
}
.messages li.error { background: var(--error); }

/* login */
.auth-wrap { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.auth-card {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 40px 44px; width: 100%; max-width: 420px;
}
.auth-card svg { width: 170px; height: auto; display: block; margin-bottom: 8px; }
.auth-card h1 { font-size: 22px; margin: 22px 0 6px; }
.dev-note {
  margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--taupe-25);
  font-size: 12px; color: var(--stone);
}

/* empty state */
.empty {
  background: var(--white); border: 1px dashed var(--taupe); border-radius: var(--r);
  padding: 48px; text-align: center; color: var(--stone);
}

@media (max-width: 1080px) {
  .detail-cols { grid-template-columns: 1fr; }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .dates-grid { min-width: 0; }
  .deal-head { flex-direction: column; }
  .stepper { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 760px) {
  .portal-top .inner { padding: 14px 20px; gap: 12px; }
  .portal-top svg { width: 104px; }
  .portal-top .pt-label { border-left: none; padding-left: 0; }
  .portal-body { padding: 24px 20px 60px; }
  .portal-progress { grid-template-columns: 1fr; }
  #shell { flex-direction: column; }
  aside {
    width: 100%; height: auto; position: static;
    border-right: none; border-bottom: 1px solid var(--taupe);
  }
  nav { display: flex; flex-wrap: wrap; gap: 2px; padding: 8px 12px; }
  .nav-item { width: auto; margin-bottom: 0; padding: 7px 11px; font-size: 13.5px; }
  .nav-sep, .nav-label, .user-chip { display: none; }
  .logo-wrap { padding: 14px 20px 10px; display: flex; align-items: baseline; gap: 14px; border-bottom: none; }
  .logo-wrap svg { width: 112px; }
  .logo-sub { margin-top: 0; }
  main { padding: 24px 20px 60px; }
  .stats { grid-template-columns: repeat(2, 1fr); }
}
/* --- long lists: paging and multi-select ------------------------------------
   New in People & Teams, which is the first surface here that has to survive a few
   hundred rows. Square corners, hairline taupe, no fills — the same rules as tables. */
.pager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-top: 16px;
}
.pager-links { display: flex; align-items: center; gap: 8px; }
/* A dead end reads as an unavailable control, not as a link that failed. */
.btn.is-off { opacity: .4; cursor: default; }

.pick-list {
  border: 1px solid var(--taupe); border-radius: var(--r);
  max-height: 320px; overflow-y: auto; background: var(--white);
}
.pick {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 9px 12px; border-bottom: 1px solid var(--taupe-25); cursor: pointer;
}
.pick:last-child { border-bottom: none; }
.pick:hover { background: var(--taupe-15); }
.pick input { margin-top: 3px; flex: none; }
.pick span { display: flex; flex-direction: column; gap: 1px; line-height: 1.35; }

/* --- borrower question cards -------------------------------------------------
   Closed until asked for. Every thread rendered open made a twenty-question page
   metres long, with the three that needed answering lost in it. So the closed state
   carries what decides whether to open: whose turn it is, how much has been said,
   and when. Built on <details>, so it opens with a keyboard and without script. */
.q-card {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  margin-bottom: 8px; scroll-margin-top: 20px;
}
/* The one waiting on the borrower is marked on its edge rather than filled: orange is
   allowed on one or two small things per screen, never as a background. */
.q-card.needs-you { border-left: 2px solid var(--pop); }
.q-card:target { border-color: var(--slate); }
.q-card > summary {
  display: flex; align-items: flex-start; gap: 14px; padding: 13px 18px 13px 16px;
  cursor: pointer; list-style: none;
}
.q-card > summary::-webkit-details-marker { display: none; }
.q-card > summary:hover { background: var(--taupe-15); }
.q-card > summary:focus-visible { outline: 2px solid var(--slate); outline-offset: -2px; }
/* A caret drawn in CSS, so there is no image to load and no emoji. */
.q-card > summary::after {
  content: ''; flex: none; margin-left: 4px; margin-top: 5px;
  width: 6px; height: 6px; border-right: 1.5px solid var(--stone);
  border-bottom: 1.5px solid var(--stone); transform: rotate(-45deg);
  transition: transform .12s ease;
}
.q-card[open] > summary::after { transform: rotate(45deg); }
.q-card[open] > summary { background: var(--taupe-15); }
.q-card-main { flex: 1; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.q-card-main .qtext { font-size: 14px; line-height: 1.4; }
.q-card-meta { font-size: 12px; color: var(--stone); }
.q-card-body {
  border-top: 1px solid var(--taupe-25); padding: 16px 18px 18px;
  background: var(--taupe-15);
}
@media (max-width: 700px) {
  /* The status chip drops under the text rather than squeezing it to nothing. */
  .q-card > summary { flex-wrap: wrap; }
  .q-card-main { flex-basis: 100%; }
}

/* Two controls that belong together — move the stage, set the badge. Label spans, then
   the select and its button share a row, so each form is two lines rather than three. */
.rail-forms {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--taupe-25);
  display: grid; gap: 12px;
}
.rail-forms form { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: end; }
.rail-forms label { grid-column: 1 / -1; display: block; margin-bottom: -4px; }
.rail-forms select {
  font-family: inherit; font-size: 13.5px; padding: 7px 10px; width: 100%;
  border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal); outline: none;
}
.rail-forms select:focus { border-color: var(--slate); }
.rail-links {
  display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 10px;
  padding-top: 10px; border-top: 1px solid var(--taupe-25);
}
.rail-links .btn { padding-left: 0; padding-right: 0; }

/* Reference cards below the two columns rather than at the bottom of the rail, which is
   what made the rail outrun the checklist by 500px while the space beside it was blank. */
.detail-band {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 14px; margin-top: 4px; align-items: start;
}
.detail-band .rail-card { margin-bottom: 0; }

/* --- notification inbox ------------------------------------------------------
   Grouped by day, because "when did this happen" is answered better by a heading than
   by repeating the date on forty rows. */
.note-day { margin-bottom: 20px; }
.note-day > h3 {
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stone); font-weight: 500; margin-bottom: 8px;
}
.note-row {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 11px 14px; margin-bottom: 6px;
}
/* Unread is marked on the edge, not filled: orange on small things, never as a ground. */
.note-row.fresh { border-left: 2px solid var(--pop); }
.note-main { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.note-title { font-size: 14px; font-weight: 500; }
.note-body { font-size: 13px; color: var(--stone); }
.note-meta { font-size: 11.5px; color: var(--stone); }
.note-meta a { color: var(--slate); }

/* -- Box Content Explorer -------------------------------------------------
 *
 * The data room is Box's own element, so its markup and most of its CSS arrive from
 * cdn01.boxcdn.net and are not ours to edit. This is a restraint layer over the top, not
 * a reskin: the font, the square corners and the hairline border, so it sits in a PFG
 * page rather than looking pasted into one. Box's blues stay where they are — chasing
 * every one of them across a third-party stylesheet is a fight that resumes on every
 * version bump, and the pinned version in `integrations/box_client.py` is what makes the
 * bump deliberate.
 *
 * The explicit height is load-bearing, not decoration: the element measures its own
 * container to work out how many rows to render, and in a container with no height it
 * collapses to nothing and reads as a failed load.
 */
.box-explorer {
  height: 620px;
  border: 1px solid var(--taupe);
  border-radius: var(--r);
  background: var(--white);
  overflow: hidden;
}
.box-explorer .be,
.box-explorer .be * { font-family: var(--font) !important; }
.box-explorer .be { border: 0; border-radius: 0; }
.box-explorer .be-header { background: var(--taupe-15); border-bottom: 1px solid var(--taupe); }
.box-explorer .btn,
.box-explorer .be-btn-add { border-radius: var(--r) !important; box-shadow: none !important; }

@media (max-width: 760px) { .box-explorer { height: 480px; } }

@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* ── the deal agent ─────────────────────────────────────────────────────────
   A floating entry point to the agents, on any page of a deal. Square corners at
   2px, hairline taupe borders, no shadow, no gradient, no pill — the design
   language applies to a floating control as much as to anything else, and a
   drop-shadowed round button would read as somebody else's product bolted on.

   Orange appears on exactly one thing here: the mark on the button. That is the
   "one or two small things per screen" allowance, spent deliberately, because this
   is the one control on the page that has to be findable without being looked for. */
.agent-fab {
  position: fixed; right: 24px; bottom: 24px; z-index: 60;
  display: flex; align-items: center; gap: 8px;
  padding: 10px 16px; font: inherit; font-size: 13px; letter-spacing: .02em;
  color: var(--charcoal); background: var(--white);
  border: 1px solid var(--taupe); border-radius: var(--r); cursor: pointer;
}
.agent-fab:hover { border-color: var(--slate); }
.agent-fab-mark {
  color: var(--pop); font-size: 14px; line-height: 1;
  transition: transform .44s var(--spring-up);
}
.is-open .agent-fab-mark { transform: rotate(135deg); }
@media (prefers-reduced-motion: reduce) {
  .agent-fab-mark { transition: none; }
}
.is-open .agent-fab { border-color: var(--slate); }

.agent-panel {
  position: fixed; right: 24px; bottom: 76px; z-index: 61;
  display: flex; flex-direction: column;
  width: 400px; max-width: calc(100vw - 48px);
  max-height: min(680px, calc(100vh - 120px));
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
}
/* THE `hidden` ATTRIBUTE NEEDS THIS RULE, and its absence is why the panel opened
   itself and would not close. A browser's built-in stylesheet says `[hidden] {
   display: none }`, but ANY author rule that sets `display` beats it — and the rule
   above sets `display: flex`. So the panel ignored `hidden` completely: it rendered
   open on every deal page, and the close button set an attribute with no visible
   effect. Anything given `display` in this file and toggled with `hidden` needs the
   same line. */
.agent-panel[hidden] {
  display: none;
  opacity: 0;
  transform: translateY(24px) scale(.97);
  /* THE WAY OUT. The transition that runs is the one on the state being moved TO, so
     the pull-down lives here and the rise lives on the rule below. */
  transition:
    opacity .13s var(--ease),
    transform .2s var(--spring-down),
    display .2s allow-discrete;
}

/* THE WAY IN: it springs up out of the button and overshoots slightly before settling.
   `transform-origin` at the bottom right is what makes the scale read as the panel
   growing from the control that opened it rather than appearing near it.

   NO JAVASCRIPT IS INVOLVED, deliberately. `display` is in the transition list with
   `allow-discrete`, which is what lets an element animate out of `display: none` and
   back. The alternative is holding the panel in the layout after it closes and removing
   it on a timer or a transitionend event — more code, and stuck open whenever that event
   does not arrive. A browser without `allow-discrete` or `@starting-style` shows and
   hides it instantly, which is the right fallback: the panel works, it just does not
   spring.

   The rise is longer than the drop because the overshoot needs room to be legible;
   neither is long enough to wait for. */
.agent-panel {
  opacity: 1;
  transform: translateY(0) scale(1);
  transform-origin: 100% 100%;
  transition:
    opacity .16s var(--ease),
    transform .44s var(--spring-up),
    display .44s allow-discrete;
}

/* The state it springs FROM. Without this the panel would animate out on close and then
   appear instantly on open — a lopsidedness that reads as a glitch rather than a choice. */
@starting-style {
  .agent-panel {
    opacity: 0;
    transform: translateY(24px) scale(.97);
  }
}

/* Somebody who asked for no motion gets the panel immediately, with no movement at all.
   The rule is "no animation", never "no feature". */
@media (prefers-reduced-motion: reduce) {
  .agent-panel,
  .agent-panel[hidden] { transition: none; }
  .agent-panel[hidden] { transform: none; }
  @starting-style {
    .agent-panel { opacity: 1; transform: none; }
  }
}

.agent-panel-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  padding: 14px 16px; border-bottom: 1px solid var(--taupe);
}
.agent-panel-deal { font-size: 14px; font-weight: 500; color: var(--charcoal); }
.agent-close {
  font: inherit; font-size: 20px; line-height: 1; padding: 0 2px;
  color: var(--stone); background: none; border: 0; cursor: pointer;
}
.agent-close:hover { color: var(--charcoal); }

.agent-section-label {
  font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stone); margin-bottom: 8px;
}
.agent-actions { padding: 14px 16px; border-bottom: 1px solid var(--taupe-25); }
.agent-actions form { margin: 0 0 6px; }
.agent-action {
  display: block; width: 100%; text-align: left;
  padding: 9px 11px; margin-bottom: 6px; font: inherit;
  background: var(--white); border: 1px solid var(--taupe);
  border-radius: var(--r); cursor: pointer;
}
.agent-action:hover { border-color: var(--slate); }
.agent-action-name {
  display: block; font-size: 13px; color: var(--charcoal); font-weight: 500;
}
.agent-action-note {
  display: block; font-size: 11px; color: var(--stone); margin-top: 2px;
}
/* Not available yet, or not for this role. Legible, obviously inert, not a button. */
.agent-action.is-idle { cursor: default; background: var(--taupe-15); border-style: dashed; }
.agent-action.is-idle:hover { border-color: var(--taupe); }

.agent-chat {
  display: flex; flex-direction: column; min-height: 0; flex: 1;
  padding: 14px 16px 16px;
}
.agent-thread { flex: 1; overflow-y: auto; min-height: 120px; margin-bottom: 10px; }
.agent-hint { font-size: 11px; color: var(--stone); margin: 0; }
.agent-msg { margin-bottom: 12px; font-size: 13px; }
.agent-msg-who {
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--stone); margin-bottom: 3px;
}
.agent-msg p { margin: 0 0 6px; line-height: 1.5; color: var(--charcoal); }
/* The answer, once it is formatted rather than printed. Rene: "don't use **, write in
   bold letters, use bullets, be polished." Emphasis is weight and slate, never a colour
   fill and never orange — an answer is not a status. */
.agent-msg-body > :last-child { margin-bottom: 0; }
.agent-msg-body strong { font-weight: 600; color: var(--charcoal); }
.agent-msg-user .agent-msg-body strong { color: var(--slate); }
.agent-msg-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px; background: var(--taupe-15); padding: 1px 4px;
  border-radius: var(--r);
}
/* A lead-in line: the label above a short list, set apart by weight and a little air. */
.agent-msg-body .agent-lead {
  font-weight: 600; color: var(--charcoal); margin: 10px 0 4px;
}
.agent-msg-body .agent-lead:first-child { margin-top: 0; }
.agent-msg-body ul, .agent-msg-body ol {
  margin: 0 0 8px; padding-left: 18px; line-height: 1.5; color: var(--charcoal);
}
.agent-msg-body li { margin: 0 0 3px; }
.agent-msg-body li.is-sub { margin-left: 14px; list-style-type: circle; }
.agent-msg-body ol li.is-sub { list-style-type: lower-alpha; }
/* A comparison the model chose to lay out as a table. Hairlines and no fill, like every
   other table in this application. */
.agent-table {
  width: 100%; border-collapse: collapse; margin: 0 0 8px; font-size: 12px;
}
.agent-table th, .agent-table td {
  border-bottom: 1px solid var(--taupe-25); padding: 4px 8px 4px 0;
  text-align: left; vertical-align: top;
}
.agent-table th {
  font-weight: 600; color: var(--stone); font-size: 10.5px;
  letter-spacing: .04em; text-transform: uppercase;
}
.agent-msg-user p { color: var(--slate); }
.agent-msg-source {
  font-size: 10px; color: var(--stone); margin-top: 4px;
  padding-top: 4px; border-top: 1px solid var(--taupe-25);
}
/* The error colour, and only for a real failure — the rule is that it means declined
   or failed, never "heads up". */
.agent-msg.is-error p { color: var(--error); }
.agent-thinking { font-size: 12px; color: var(--stone); }
.agent-thinking::after {
  content: ""; display: inline-block; width: 9px; height: 9px; margin-left: 7px;
  border: 1.5px solid var(--taupe); border-top-color: var(--slate);
  border-radius: 50%; vertical-align: -1px;
  animation: pfg-spin .7s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .agent-thinking::after { animation: none; }
}
.agent-form { display: flex; gap: 8px; align-items: flex-end; }
.agent-form textarea {
  flex: 1; font: inherit; font-size: 13px; padding: 8px 10px; resize: vertical;
  color: var(--charcoal); background: var(--white);
  border: 1px solid var(--taupe); border-radius: var(--r);
}
.agent-form textarea:focus { outline: none; border-color: var(--slate); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* On a narrow screen it takes the width and sits above the sidebar. */
@media (max-width: 720px) {
  .agent-panel { right: 12px; left: 12px; width: auto; bottom: 68px; }
  .agent-fab { right: 12px; bottom: 12px; }
}


/* INTERNAL NOTE CARDS. Built to the same shape as .q-card, for the same reason: a page
   of notes rendered open runs metres long and one very long note buries every note after
   it. Rene, having tried exactly that. <details> again, so it opens with a keyboard and
   without script.

   Unlike .q-card, collapsing here is ONLY about finding the next note: this page is
   internal and a borrower is refused before any of it renders, so nothing is kept private
   by being folded up. */
.note-card {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  margin-bottom: 8px; scroll-margin-top: 20px;
}
/* Affinity's notes are marked on the edge rather than filled — the rule that keeps the
   interface free of coloured backgrounds, and the same treatment .q-card.needs-you gets. */
.note-card.from-affinity { border-left: 2px solid var(--stone); }
.note-card > summary {
  display: flex; flex-direction: column; gap: 4px; padding: 12px 34px 12px 16px;
  cursor: pointer; list-style: none; position: relative;
}
.note-card > summary::-webkit-details-marker { display: none; }
.note-card > summary:hover { background: var(--taupe-15); }
.note-card > summary:focus-visible { outline: 2px solid var(--slate); outline-offset: -2px; }
/* The caret is absolutely positioned because the summary stacks two lines here, and a
   flex caret would sit against the first of them rather than the card. */
.note-card > summary::after {
  content: ''; position: absolute; right: 16px; top: 17px;
  width: 6px; height: 6px; border-right: 1.5px solid var(--stone);
  border-bottom: 1.5px solid var(--stone); transform: rotate(-45deg);
  transition: transform .12s ease;
}
.note-card[open] > summary::after { transform: rotate(45deg); }
.note-card[open] > summary { background: var(--taupe-15); }
.nc-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  font-size: 13px;
}
/* The closed line: one line, truncated with an ellipsis rather than wrapping, so every
   card is the same height and the list can be scanned down its left edge. */
.nc-peek {
  font-size: 13px; color: var(--stone); line-height: 1.45;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.note-card[open] > summary .nc-peek { display: none; }
.nc-body {
  border-top: 1px solid var(--taupe-25); padding: 14px 18px 16px;
  background: var(--taupe-15); font-size: 14px; line-height: 1.55;
  white-space: normal; overflow-wrap: anywhere;
}
/* AN EXTRACT, AND A LINK TO ITS OWN OCCURRENCE. Indented under the heading so several
   read as a list rather than as a paragraph, and truncated to one line each so a card
   with three matches is still a card rather than a page. */
.nc-snip {
  display: block; font-size: 13px; line-height: 1.5; color: var(--charcoal);
  text-decoration: none; padding: 3px 0 3px 10px; margin-top: 2px;
  border-left: 1px solid var(--taupe);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nc-snip:hover { border-left-color: var(--slate); }
.nc-snip:hover .nc-hit { background: var(--find-strong); }
.nc-snip:focus-visible { outline: 2px solid var(--slate); outline-offset: 2px; }

/* The matched word. Taupe-on-taupe was invisible — "the highlighting is barely visible",
   and it was: var(--taupe-25) is two shades off the card it sat on. */
.nc-hit { background: var(--find); font-weight: 600; border-radius: 1px; padding: 0 1px; }

/* Landed on from an extract. `scroll-margin-top` keeps it clear of the top of the
   window rather than jammed against it, and the stronger fill says which of four
   identical words you were sent to. */
.nc-body .nc-hit { scroll-margin-top: 90px; }
.nc-body .nc-hit:target { background: var(--find-strong); box-shadow: 0 0 0 2px var(--find-strong); }

@media (max-width: 700px) {
  .nc-head { flex-wrap: wrap; gap: 2px; }
}

/* The wordmark is a link now — home for whichever side you are on. It must not pick up
   a link's underline or colour, and it has to say it is clickable. */
a.logo-wrap, a.pt-home {
  display: block; text-decoration: none; color: inherit; cursor: pointer;
}
a.logo-wrap:hover .logo-sub { color: var(--slate); }
a.logo-wrap:focus-visible, a.pt-home:focus-visible {
  outline: 2px solid var(--slate); outline-offset: 3px;
}


/* THE FOUR WORKSPACES. Rene: "the most important sections are small buttons at the top,
   so they don't get enough attention." They were secondary buttons in a row with
   "Archive deal", which said they were the same kind of thing.

   Four across on a full-width deal page; the minimum is checked against the real content
   width rather than guessed, because a grid that silently drops to three columns and
   leaves dead space at the right edge is a trap this stylesheet has already fallen into
   once — see the pipeline note above. 1144px of content over four columns with a 10px
   gap leaves 256 each, so the minimum sits under that. */
/* Four fixed columns, never auto-fill. auto-fill made as many 245px tracks as would fit
   and left the last two empty, so four cards stopped 500px short of the right edge -
   the trap the pipeline grid note above already describes. */
.workspaces {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 16px; margin: 0 0 16px;
}
.ws-card {
  display: block; text-decoration: none; color: inherit;
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 12px 13px 13px; transition: border-color .12s var(--ease); min-width: 0;
}
.ws-card:hover { border-color: var(--slate); }
.ws-card:focus-visible { outline: 2px solid var(--slate); outline-offset: 2px; }
.ws-title {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--stone); margin-bottom: 7px;
}
/* The state, not the label — it is what somebody is here to read. */
.ws-headline { font-size: 14px; line-height: 1.3; color: var(--charcoal); }
.ws-detail { font-size: 11.5px; line-height: 1.4; color: var(--stone); margin-top: 3px; }

/* PFG has to do something here. On the EDGE, never as a fill: the design language allows
   orange on one or two small things per screen and never as a background. Same treatment
   .q-card.needs-you gets, for the same reason. */
.ws-card.needs-you { border-left: 2px solid var(--pop); }
/* Nothing has happened here yet, which early in a deal is normal rather than a problem.
   Quieter, so the cards that DO say something carry the eye. */
.ws-card.quiet { background: var(--taupe-15); }
.ws-card.quiet .ws-headline { color: var(--stone); font-size: 14px; }


/* The CRM's state, inside the record rather than beside it. Separated by a rule rather
   than a heading: it is part of the record, not a second subject. */
.rec-crm {
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--taupe-25);
}





/* ============================================================================
   THE DEAL PAGE — four zones, each thing in one place.
   ============================================================================ */

/* Zone 1: identity left, the record right. .deal-head is the shared flex header; this
   page gives it a right-hand panel of fixed width so the dates grid and the controls
   line up as one column regardless of how long the deal name runs. */
.deal-id { flex: 1 1 480px; min-width: 0; }
/* The deal page's header keeps the page's 16px unit beneath it; the shared .deal-head
   keeps its own value for the screens that use it. */
.deal-head--deal { margin-bottom: 16px; }
/* Two equal buttons filling the record card's width. */
.rec-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.rec-actions .btn { display: block; text-align: center; }
.deal-badges { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
/* The stepper is a div now, but keep the strip's own padding explicit so a future
   element rule cannot indent it either. */
.stepper { padding: 0; }
/* The record's controls, beside the task list. A rail-card like its neighbours, so it
   reads as one of the page's cards and not as a panel of a different species. */
.deal-record { display: flex; flex-direction: column; gap: 8px; }
.deal-record h4 { margin-bottom: 4px; }
/* A column flex container stretches its children, which turned every button in
   these cards into a full-width bar that reads as a text input. Buttons size to
   their label. */
.deal-record > .btn, .deal-record .dn-terms + .btn { align-self: flex-start; }

/* SAME HEIGHT AS THE TASK LIST. Rene: "Can you make it the same height?" The shared
   .detail-cols aligns to the top, which other screens rely on, so this page adds a
   modifier that stretches instead. Every margin between the two boxes is zeroed here -
   a grid item's own margin sits inside its track, so a 12px card margin would have left
   the record 12px short of the tasks and looked like a mistake rather than a match. The
   hidden stage panels are display:none and so cost the row nothing. */
/* ONE SPACING UNIT. Rene: "make sure the vertical and horizontal space between views is
   symmetrical across the board" - it was not: gutters of 6, 10, 14 and 22px and row gaps
   of 18, 20 and 36 on one page. Every gutter and every gap between rows on the deal page
   is now 16px, set here and on .workspaces, .stepper, .detail-band and .deal-head--deal.
   The one deliberate exception is the break above the reference row, which is two units
   because it separates zones rather than rows, and was asked for. */
.detail-cols--level { align-items: stretch; gap: 16px; margin-bottom: 32px; }
.detail-cols--level > .stage-work { margin-bottom: 0; }
.detail-cols--level > .stage-work > .stage-panel { margin-bottom: 0; height: 100%; }
.detail-cols--level > .deal-record { margin-bottom: 0; }
/* With the card stretched, the quiet actions sit at its foot: controls at the top,
   record-keeping at the bottom, and the space between is deliberate. */
.detail-cols--level > .deal-record > .ctl-actions { margin-top: auto; }

/* A control row: label, the control, its button. Label width fixed so the selects
   align down the panel; the select takes the remaining width. */
.ctl-row { display: flex; align-items: center; gap: 8px; margin: 0; }
.ctl-row > label, .ctl-row > .ic-label {
  flex: 0 0 48px; font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--stone);
}
.ctl-row > select { flex: 1 1 auto; min-width: 0; font-size: 13px; padding: 6px 8px; }
.ctl-row > .btn { flex: 0 0 auto; }
.ic-row { padding-top: 8px; border-top: 1px solid var(--taupe-25); }
/* Two lines by design, not by wrapping: the decision, then what it gates. */
.ic-state { flex: 1 1 auto; font-size: 13px; line-height: 1.35; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ic-state .ic-sub { font-size: 11.5px; color: var(--stone); }

/* Rare actions as quiet links, not a row of identical buttons. */
.ctl-actions {
  display: flex; gap: 14px; flex-wrap: wrap; padding-top: 8px;
  border-top: 1px solid var(--taupe-25); font-size: 12px;
}
.ctl-actions a { color: var(--slate); text-decoration: none; }
.ctl-actions a:hover { text-decoration: underline; }

/* Zone 4: three cards, one row, equal height. Stretch, not start — the cards are sized
   so stretching costs nothing, and a ragged bottom edge is what a row must never have. */
.detail-band {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  /* A zone break, not a row gap: the work above and the reference below are different
     kinds of thing, and Rene asked for more air here. Twice the spacing used within
     a zone, so the eye reads it as a boundary. */
  gap: 16px; margin-top: 0; align-items: stretch;
  /* Room beneath the last row so the floating deal-agent button never sits on it. */
  margin-bottom: 72px;
}
.detail-band .rail-card { margin-bottom: 0; display: flex; flex-direction: column; }
.detail-band .card-link, .detail-band .card-links { margin-top: auto; }

.side-label {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--stone);
  margin: 12px 0 4px;
}
.side-label:first-of-type { margin-top: 0; }

/* A person: name, role, and a quiet way off the deal. Grid so roles align in a column
   and the remove control sits in the same spot on every row. */
.person {
  display: grid; grid-template-columns: minmax(0, 1fr) auto 22px; align-items: center;
  gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--taupe-25); font-size: 13px;
}
.person:last-of-type { border-bottom: 0; }
.p-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-role { font-size: 12px; color: var(--stone); white-space: nowrap; }
.person form { display: contents; }
.p-remove {
  width: 22px; height: 22px; border: 0; background: none; color: var(--taupe);
  font-size: 16px; line-height: 1; cursor: pointer; border-radius: var(--r);
}
.p-remove:hover { color: var(--error); background: var(--taupe-15); }
.p-flag { margin-top: 8px; }
.p-flag a { color: inherit; }
.add-person { display: flex; gap: 6px; margin-top: 8px; }
.add-person select { flex: 1 1 auto; min-width: 0; font-size: 13px; padding: 6px 8px; }

/* Every control in these panels takes the site's field look. Nothing outside .field or
   .controls gets it otherwise, which is how a textarea here rendered in the browser's
   monospace default and the selects in a system font. */
.ctl-row > select, .add-person select, .inote-form textarea {
  font-family: inherit; font-size: 13px; color: var(--charcoal);
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  outline: none;
}
.ctl-row > select:focus, .add-person select:focus, .inote-form textarea:focus {
  border-color: var(--slate);
}

/* Notes: the box full width, its button beneath and to the right; each note as author
   line over text, the text held to two lines so three notes are three notes tall. */
.inote-form { margin-bottom: 6px; }
.inote-form textarea {
  display: block; width: 100%; min-height: 56px; padding: 8px 10px; resize: vertical;
  line-height: 1.45;
}
.inote-form-foot { display: flex; justify-content: flex-end; margin-top: 6px; }
.inote { padding: 8px 0; border-bottom: 1px solid var(--taupe-25); }
.inote:last-of-type { border-bottom: 0; }
.inote-meta { font-size: 11.5px; color: var(--stone); margin-bottom: 2px; }
.inote-text {
  font-size: 13px; line-height: 1.45; color: var(--charcoal);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Activity rows: what happened, and when, on one line. */
.act-row {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
  padding: 6px 0; border-bottom: 1px solid var(--taupe-25);
}
.act-row:last-of-type { border-bottom: 0; }
.act-row b { font-weight: 500; }
.act-row .tiny { white-space: nowrap; }

/* The link at the foot of a card. One style, every card, same place. */
.card-link {
  display: inline-block; margin-top: 10px; font-size: 12.5px; color: var(--slate);
  text-decoration: none;
}
.card-link:hover { text-decoration: underline; }
.card-links { display: flex; gap: 14px; flex-wrap: wrap; }
.card-links .card-link { margin-top: 10px; }

/* The stage panel head. */
.sn-head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; margin-bottom: 8px;
}
.sn-head h4 { margin: 0; }

@media (max-width: 1100px) {
  .deal-record { flex: 1 1 100%; }
  .detail-band { grid-template-columns: 1fr; }
  .workspaces { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* PROPOSED TERMS. The form is the table: same sixteen rows, same order, so what the
   deal team fills in has the shape of what the committee reads. A label column wide
   enough for "Concentration Limits" without wrapping, and the value beside it. */
.terms-grid {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  overflow: hidden;
}
.term-row {
  display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 16px;
  align-items: start; padding: 10px 16px; border-bottom: 1px solid var(--taupe-25);
}
.term-row:last-child { border-bottom: 0; }
.term-row > label {
  font-size: 12.5px; color: var(--charcoal); padding-top: 9px; line-height: 1.3;
}
.term-input {
  width: 100%; font-family: inherit; font-size: 13.5px; line-height: 1.45;
  padding: 7px 10px; border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal); outline: none; resize: vertical;
}
.term-input:focus { border-color: var(--slate); }
/* The placeholder carries what the note will print if the row is left alone, so it is
   readable rather than a hint to squint at. */
.term-input::placeholder { color: var(--stone); opacity: 1; }
.terms-foot {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 16px;
}
.terms-foot .tiny { flex: 1 1 320px; }
@media (max-width: 800px) {
  .term-row { grid-template-columns: 1fr; gap: 4px; }
  .term-row > label { padding-top: 0; }
}


/* THE DEAL NOTES PAGE. Versions on the left, the terms they were built from beside
   them — reading a draft with its inputs off-screen is how a wrong figure gets past. */
.dn-row { padding: 10px 0; border-bottom: 1px solid var(--taupe-25); }
.dn-row:last-of-type { border-bottom: 0; }
.dn-main b { font-weight: 500; }
.dn-main .tiny { margin-top: 2px; }
.dn-write {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--taupe-25);
}
.dn-write .tiny { flex: 1 1 220px; }

/* The sixteen rows as a summary: label and value on one line each, truncated. The full
   text is on the terms screen — this is for checking what the note will say, not for
   reading the covenants. */
.dn-terms { display: flex; flex-direction: column; }
.dn-term {
  display: grid; grid-template-columns: 116px minmax(0, 1fr); gap: 10px;
  padding: 4px 0; border-bottom: 1px solid var(--taupe-25); font-size: 12px;
}
.dn-term:last-child { border-bottom: 0; }
.dn-term-label { color: var(--stone); }
.dn-term-value {
  color: var(--charcoal); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* An unanswered row is quiet, not alarming: a deal still being structured is the normal
   state, and sixteen warnings would say nothing. */
.dn-term.unset .dn-term-value { color: var(--stone); font-style: italic; }

/* A proposed row: marked on its edge so the eye can find what the agent touched among
   what a person typed, and never filled — a coloured background would read as confirmed.
   The source sits under the box, because a value nobody can check is not help. */
.term-row.proposed { border-left: 2px solid var(--pop); }
.term-src { font-size: 11.5px; color: var(--stone); margin-top: 4px; }

/* What a draft could not complete. Folded, because it is a checklist to work through
   rather than a warning to read every time — and because unfolded it is the list that
   used to make the document a fifth too long. */
.dn-gaps { margin-top: 4px; }
.dn-gaps > summary { cursor: pointer; list-style: none; }
.dn-gaps > summary::-webkit-details-marker { display: none; }
.dn-gaps > summary::before { content: '▸ '; }
.dn-gaps[open] > summary::before { content: '▾ '; }
.dn-gaps > div { padding: 2px 0 2px 14px; }


/* THE NOTE EDITOR. A section reads as it will print; the editor is one click behind it,
   because a draft is read far more often than it is changed. */
.ns {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 16px 18px; margin-bottom: 16px; scroll-margin-top: 20px;
}
.ns:target { border-color: var(--slate); }
.ns-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 14px;
  margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--taupe-25);
}
.ns-head h4 { margin: 0; }
.ns-meta { font-size: 11.5px; color: var(--stone); white-space: nowrap; }
/* A section a person rewrote is a different thing to a reviewer from one the model
   produced, and that difference is invisible in the finished file. */
.ns-touched { color: var(--slate); }
.ns-read {
  font-size: 13.5px; line-height: 1.6; color: var(--charcoal);
  max-width: 70ch; white-space: pre-wrap;
}
.ns-gaps { color: var(--stone); margin-top: 10px; }
.ns-tools { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--taupe-25); }
.ns-tools > summary {
  cursor: pointer; list-style: none; color: var(--slate);
}
.ns-tools > summary::-webkit-details-marker { display: none; }
.ns-tools > summary::before { content: '▸ '; }
.ns-tools[open] > summary::before { content: '▾ '; }
.ns-editor {
  display: block; width: 100%; margin-top: 10px; padding: 10px 12px;
  font-family: inherit; font-size: 13.5px; line-height: 1.6; resize: vertical;
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  color: var(--charcoal); outline: none;
}
.ns-editor:focus { border-color: var(--slate); }
.ns-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.ns-actions .tiny { flex: 1 1 260px; }
/* Asking for it again, in your own words. Beneath the editor because rewriting it
   yourself is the more certain of the two. */
.ns-redraft {
  display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px;
  padding-top: 10px; border-top: 1px dashed var(--taupe-25);
}
.ns-instruction {
  flex: 1 1 320px; min-width: 0; padding: 7px 10px; font-family: inherit;
  font-size: 13px; border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal); outline: none;
}
.ns-instruction:focus { border-color: var(--slate); }
/* The export link beside a version in the list. */
.dn-export { margin-left: 10px; font-size: 12px; }

/* The reading view of a section: how it will print, not how it is typed. */
.ns-read { white-space: normal; }
.ns-read p { margin: 0 0 8px; }
.ns-sub {
  font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--pop); margin: 12px 0 6px;
}
.ns-bullet { position: relative; padding-left: 16px; margin-bottom: 5px; }
.ns-bullet::before { content: '•'; position: absolute; left: 3px; color: var(--stone); }
.ns-bullet.sub { padding-left: 32px; }
.ns-bullet.sub::before { content: '–'; left: 19px; }
.ns-read b { font-weight: 600; }
.ns-table { border-collapse: collapse; margin: 8px 0; font-size: 12.5px; width: 100%; }
.ns-table th, .ns-table td {
  border: 1px solid var(--taupe-25); padding: 5px 8px; text-align: left; vertical-align: top;
}
.ns-table th { color: var(--stone); font-weight: 500; }


/* ============================================================================
   THE DEAL NOTE, AS A DOCUMENT YOU TYPE IN.

   Rene: "If the screen doesn't look like almost a real word editor, do not even dare."
   So the measurements are the .docx's own, converted from twips at 96dpi rather than
   guessed: A4 is 11906 x 16838 twips = 794 x 1123px; the corpus margins are 1080 twips
   left and right = 72px, 567 top = 38px. Garamond 11pt body, Century Gothic headings,
   595959 section bars, ED7D31 sub-headings, F2F2F2 callout — all from docx_writer.py.
   If those constants change there, they change here.
   ============================================================================ */

/* The toolbar. Deliberately thin: it is a document's chrome, not an application's. */
.doc-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; margin-bottom: 16px;
}
.doc-bar .back { margin: 0; }
.doc-bar-right { display: flex; align-items: center; gap: 14px; }
.doc-status { font-size: 12px; color: var(--stone); min-width: 130px; text-align: right; }
.doc-status.bad { color: var(--error); }
.doc-words { font-size: 12px; color: var(--stone); font-variant-numeric: tabular-nums; }

/* The page and its rail. Rene: "Let's have a toolbar at the right." The rail is a
   sibling rather than something floating over the document, so nothing it does can cover
   a word somebody is reading. Below 1180px there is no room for both and it drops under
   the page, which is the right answer on a laptop in a meeting. */
.doc-layout {
  display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 28px;
  align-items: start;
}
@media (max-width: 1180px) {
  .doc-layout { grid-template-columns: minmax(0, 1fr); }
  .doc-rail { position: static !important; max-height: none !important; }
}

/* The stage the page sits on. Grey, so the white page reads as paper. */
.doc-stage { padding: 0 0 72px; display: flex; justify-content: center; }
.doc-page {
  width: 794px; max-width: 100%; background: var(--white);
  border: 1px solid var(--taupe); box-shadow: var(--shadow);
  padding: 72px 72px 80px;
  font-family: Garamond, 'EB Garamond', 'Times New Roman', serif;
  font-size: 14.7px;         /* 11pt */
  line-height: 1.45; color: #000;
}

/* The document's own header block, as the .docx prints it. */
.doc-header {
  display: grid; grid-template-columns: 1fr 1fr; gap: 2px 16px;
  border-bottom: 1px solid #A0A0A0; padding-bottom: 8px; margin-bottom: 22px;
  font-family: 'Century Gothic', var(--font); font-size: 11.7px; color: #333;
}
.doc-header-right { grid-column: 2; text-align: right; }

/* A section heading: white Century Gothic on the dark grey bar. The single most
   recognisable thing about a PFG note. */
.doc-h {
  background: #595959; color: #fff;
  font-family: 'Century Gothic', var(--font); font-size: 14.7px; font-weight: 500;
  letter-spacing: .02em; padding: 5px 10px; margin: 24px 0 12px;
}
.doc-section:first-of-type .doc-h { margin-top: 0; }

/* The editable region. No box, no border, no focus ring around the whole thing — it is
   the page. The only affordance is the caret, which is what a document gives you. */
.doc-body { outline: none; }
.doc-body:focus { outline: none; }
.doc-para { margin: 0 0 8px; }
.doc-para:empty::before { content: ''; display: inline-block; }
.doc-sub {
  color: #ED7D31; font-size: 16px; font-weight: 600;
  font-family: 'Century Gothic', var(--font);
  margin: 16px 0 8px; text-transform: uppercase; letter-spacing: .02em;
}
.doc-bullet { position: relative; padding-left: 20px; margin: 0 0 6px; }
.doc-bullet::before {
  content: '•'; position: absolute; left: 6px; color: #000;
}
.doc-bullet.lvl1 { padding-left: 42px; }
.doc-bullet.lvl1::before { content: '–'; left: 26px; }
.doc-body b { font-weight: 700; }

/* The conditions table. contenteditable="false" and rebuilt server-side: it is PFG's
   own recorded terms, and a second place to change them is what memo/terms.py exists
   to prevent. */
.doc-table {
  border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 13.3px;
}
.doc-table th, .doc-table td {
  border: 1px solid #BFBFBF; padding: 5px 8px; text-align: left; vertical-align: top;
}
.doc-table th { background: #F2F2F2; font-weight: 600; }
.doc-table td:first-child { width: 34%; }

/* A pasted screenshot. Sits in the flow like a figure in Word, and can be dragged to
   another place in the document. */
.doc-figure {
  margin: 12px 0; padding: 2px; border: 1px solid transparent; cursor: grab;
  max-width: 100%;
}
.doc-figure img { display: block; max-width: 100%; height: auto; }
.doc-figure:hover { border-color: var(--accent-faint); }
.doc-figure.dragging { opacity: .4; }
/* Where it would land. A line rather than a box, so the document does not jump. */
.doc-drop { border-top: 2px solid var(--slate) !important; }

/* The strip under each section: its word count, what is outstanding, and the one control
   that is not typing — asking for this section again.

   IT IS INVISIBLE UNTIL YOU ARE WORKING IN THAT SECTION. A word count and a text box
   sitting between two headings is application furniture printed on the paper, and it was
   the last thing on this page still saying "this is a form" rather than "this is the
   document". It reserves its space either way, so nothing moves when it appears — and it
   appears on focus as well as hover, so it is reachable from the keyboard.

   What is OUTSTANDING stays visible regardless. That is not chrome: it is the note
   telling a reviewer what PFG still does not know, and hiding it until somebody happens
   to hover would be hiding the most important sentence on the page. */
.doc-meta {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 10px 0 0; padding-top: 8px;
  font-family: var(--font); font-size: 11.5px; color: var(--stone);
  opacity: 0; transition: opacity .12s ease;
}
.doc-section:hover .doc-meta,
.doc-section:focus-within .doc-meta { opacity: 1; }
.doc-gap { color: var(--pop); }

/* WHICH SECTION THE AGENT IS ABOUT TO REWRITE. Rene asked for a redraft and "it touched
   the section above" — the control sits at the foot of its own section, which puts it
   directly above the NEXT heading bar. Hovering or focusing it outlines the one it will
   actually act on, so the answer is visible before the button is pressed. */
.doc-section.is-targeted .doc-body {
  box-shadow: -3px 0 0 var(--slate);
  background: #FCFCFB;
}
.doc-redraft-for {
  font-weight: 600; color: var(--slate); letter-spacing: .02em; white-space: nowrap;
}
/* While it is being rewritten, that section alone is out of action. The rest of the
   document stays editable, which is the whole point. */
.doc-section.is-redrafting .doc-body { opacity: .45; pointer-events: none; }
.doc-section.is-redrafting .doc-h::after {
  content: ' — being rewritten…'; font-size: 11.5px; opacity: .85;
  font-family: var(--font); letter-spacing: 0; text-transform: none;
}

/* The one piece of working state that stays on the paper: what this section is still
   waiting on. A closed line that opens — built on <details>, like the borrower's Q&A
   cards, so it works from a keyboard and without script. Closed, because thirteen items
   of orange text is the largest thing on a real draft and it is not part of the note;
   open, because "13 still to confirm" without the thirteen is no use to a reviewer. */
.doc-flag {
  font-family: var(--font); font-size: 11px; margin-top: 12px;
}
.doc-flag > summary {
  color: var(--pop); letter-spacing: .04em; text-transform: uppercase;
  cursor: pointer; list-style: none; width: fit-content;
}
.doc-flag > summary::-webkit-details-marker { display: none; }
.doc-flag > summary::after { content: ' ▸'; }
.doc-flag[open] > summary::after { content: ' ▾'; }
.doc-flag ul {
  margin: 6px 0 0; padding-left: 16px; color: var(--stone);
  font-size: 11.5px; line-height: 1.6; text-transform: none; letter-spacing: 0;
}
.doc-redraft { display: flex; gap: 6px; margin-left: auto; align-items: center; }
.doc-redraft input {
  width: 260px; max-width: 40vw; font-family: inherit; font-size: 11.5px;
  padding: 4px 8px; border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal); outline: none;
}
.doc-redraft input:focus { border-color: var(--slate); }
.doc-redraft button {
  font-family: inherit; font-size: 11.5px; padding: 4px 10px; cursor: pointer;
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  color: var(--charcoal);
}
.doc-redraft button:hover { border-color: var(--slate); }

@media (max-width: 860px) {
  .doc-page { padding: 24px 24px 48px; }
}

/* ---------------------------------------------------------------------------
   THE RAIL: what to do to the document, what people said about it, and what it
   used to say. Quiet by design — it is the margin of a page, not an
   application's chrome, and the document is the thing.
   --------------------------------------------------------------------------- */
/* A DIV, never an <aside>: the bare `aside` selector above is the shell's navigation —
   232px, white, full height — and it applies to any <aside> in the application. See the
   note in note_detail.html; this has caught me twice. */
.doc-rail {
  position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow-y: auto;
  font-family: var(--font); font-size: 12px;
}
/* The panels are `.rail-card`, the component the deal page already uses, so the rail is
   part of this application rather than something bolted to the side of it. */
.doc-rail .rail-card { padding: 12px 13px; }
.doc-rail .rail-card:last-child { margin-bottom: 0; }

/* A toolbar: one wrapping row of small buttons with rules between the groups, which is
   the shape every word processor has. It was a grid of eight large boxes, which read as
   a form and took more of the eye than the document. */
.rail-tools .tool-row { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.rail-tools button {
  font-family: inherit; font-size: 11.5px; line-height: 1; padding: 6px 8px;
  border: 1px solid transparent; border-radius: var(--r); background: transparent;
  color: var(--charcoal); cursor: pointer; white-space: nowrap;
}
.rail-tools button:hover { background: var(--taupe-15); border-color: var(--taupe); }
.rail-tools button:active { background: var(--taupe-25); }
.rail-tools button.tool-ico { min-width: 26px; text-align: center; }
.tool-rule { width: 1px; align-self: stretch; background: var(--taupe-25); margin: 2px 3px; }
.rail-hint {
  font-size: 11px; color: var(--stone); margin: 9px 0 0; line-height: 1.45;
  border-top: 1px solid var(--taupe-25); padding-top: 8px;
}

/* The button that appears beside a selection. Word puts the control where the words are;
   a control only in the margin is one most people never find. */
.doc-selection-tool {
  position: absolute; z-index: 45; font-family: var(--font); font-size: 11.5px;
  padding: 5px 10px; cursor: pointer; border-radius: var(--r);
  border: 1px solid var(--slate); background: var(--slate); color: #fff;
  box-shadow: var(--shadow);
}
.doc-selection-tool[hidden] { display: none !important; }
.doc-selection-tool:hover { background: var(--slate-dark); }

.rail-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  border-bottom: 1px solid var(--taupe-25); padding-bottom: 6px; margin-bottom: 9px;
}
.rail-head h4 {
  margin: 0; font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stone); font-weight: 500;
}
.rail-toggle { font-size: 11px; color: var(--stone); cursor: pointer; }
.rail-toggle input { margin-right: 3px; vertical-align: middle; }
.rail-linkish {
  background: none; border: 0; padding: 0; font-family: inherit; font-size: 11px;
  color: var(--slate); cursor: pointer; text-decoration: underline;
}

/* A comment sits beside the words it is about, which is the whole point of a margin.
   `margin-top` is set per card by the script — see positionComments. */
.rail-comment {
  border-left: 2px solid var(--pop); background: var(--taupe-15);
  padding: 8px 10px; margin-bottom: 8px; cursor: pointer;
}
.rail-comment.is-focused { border-left-color: var(--slate); box-shadow: var(--shadow); }
.rail-comment.is-resolved { opacity: .55; border-left-color: var(--taupe); }
.rc-head { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.rc-who {
  width: 20px; height: 20px; flex: none; display: grid; place-items: center;
  background: var(--slate); color: #fff; font-size: 9.5px; letter-spacing: .02em;
}
.rc-name { font-weight: 600; font-size: 11.5px; }
.rc-when { margin-left: auto; font-size: 10.5px; color: var(--stone); }
.rc-quote {
  font-size: 11px; color: var(--stone); font-style: italic;
  border-left: 2px solid var(--taupe-25); padding-left: 6px; margin-bottom: 5px;
}
.rc-quote.is-lost { color: var(--pop); font-style: normal; }
.rc-body { font-size: 12px; line-height: 1.45; white-space: pre-wrap; }
.rc-reply {
  font-size: 11.5px; line-height: 1.45; margin-top: 6px; padding-left: 8px;
  border-left: 1px solid var(--taupe-25);
}
.rc-actions { display: flex; gap: 10px; margin-top: 7px; }
.rail-comment.is-composing { border-left-color: var(--slate); cursor: default; }
.rail-comment.is-nested { margin: 8px 0 0; border-left-width: 1px; }
.rc-input {
  width: 100%; box-sizing: border-box; font-family: var(--font); font-size: 12px;
  padding: 6px; border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal); resize: vertical;
}
.rc-input:focus { outline: none; border-color: var(--slate); }
.rc-actions button.rc-post {
  text-decoration: none; border: 1px solid var(--slate); color: var(--slate);
  padding: 3px 10px; border-radius: var(--r);
}
.rc-actions button {
  background: none; border: 0; padding: 0; font-family: inherit; font-size: 11px;
  color: var(--slate); cursor: pointer; text-decoration: underline;
}

/* The highlight in the document. Yellow, because that is what a comment highlight is
   everywhere, and it is legibility rather than decoration — the same reasoning that
   put a yellow highlight on a search hit in the internal notes. */
mark.doc-mark {
  background: #FDF3C9; color: inherit; padding: 0 1px; cursor: pointer;
  box-shadow: inset 0 -1px 0 #E3C96B;
}

.rail-version {
  border-bottom: 1px solid var(--taupe-25); padding: 8px 0;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px;
}
.rail-version:last-child { border-bottom: none; padding-bottom: 0; }
.rail-version > div { width: 100%; }
.rail-version.is-now {
  border-left: 2px solid var(--slate); padding-left: 9px; margin-left: -1px;
}
.rail-version form { margin-left: auto; }

/* Table controls, floated beside the table. NOT inside the document: anything drawn
   inside a contenteditable region is something a browser will let somebody type into,
   select and delete. */
.doc-table-tools {
  position: absolute; z-index: 40; display: flex; gap: 4px;
  background: var(--white); border: 1px solid var(--taupe); padding: 3px;
  font-family: var(--font);
}
.doc-table-tools[hidden] { display: none !important; }
.doc-table-tools button {
  font-family: inherit; font-size: 11px; padding: 3px 7px; cursor: pointer;
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  color: var(--charcoal);
}
.doc-table-tools button:hover { border-color: var(--slate); color: var(--slate); }
.doc-table-tools button[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   IT HAS TO LOOK EDITABLE. Rene: "Make it visually evident that the files can be
   edited right there. For example, when hovering over text, square that whole
   section or something like that."

   So hovering a section draws it as a field: a hairline box, and a shade off the
   page when the caret is in it. The border is TRANSPARENT at rest rather than
   absent, so nothing moves by a pixel when it appears — a document that shifts
   under the pointer reads as broken however subtle the cue is.
   --------------------------------------------------------------------------- */
.doc-page[data-can-edit="1"] .doc-body {
  border: 1px solid transparent; border-radius: var(--r);
  margin: 0 -10px; padding: 2px 10px;
  transition: background-color .12s ease, border-color .12s ease;
}
.doc-page[data-can-edit="1"] .doc-body:hover { border-color: var(--taupe-25); }
.doc-page[data-can-edit="1"] .doc-body:focus,
.doc-page[data-can-edit="1"] .doc-body:focus-within {
  border-color: var(--taupe); background: #FCFCFB;
}
/* And the line under the pointer, so it is obvious which paragraph a formatting
   button is about to act on. */
.doc-page[data-can-edit="1"] .doc-body > *:hover { background: #FAFAF8; }
.doc-page[data-can-edit="1"] .doc-table td[contenteditable="true"]:hover,
.doc-page[data-can-edit="1"] .doc-table th[contenteditable="true"]:hover {
  background: #FAF7F0;
}
.doc-page[data-can-edit="1"] .doc-table td[contenteditable="true"]:focus,
.doc-page[data-can-edit="1"] .doc-table th[contenteditable="true"]:focus {
  outline: 1px solid var(--slate); outline-offset: -1px; background: #FCFCFB;
}
/* The fixed half of the conditions table says so by looking like a label rather than
   a field: those sixteen names are the format the committee reads. A row somebody
   added here is theirs, label and all. */
.doc-terms td:first-child { background: #FAFAF8; color: #333; }
.doc-terms tr.is-extra td:first-child { background: transparent; }

/* ---------------------------------------------------------------------------
   THE FACILITY IRR CALCULATOR

   The answer at the top, the inputs beside it, the working underneath. A
   calculator whose result is below the fold is a spreadsheet, and nobody
   scrolls a spreadsheet to find out whether the deal clears their hurdle.
   --------------------------------------------------------------------------- */
.irr-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; margin-bottom: 16px;
}
.irr-bar .back { margin: 0; }
.irr-bar-right { display: flex; align-items: center; gap: 10px; }
.irr-inline { display: inline; }
.irr-status {
  font-size: 12px; color: var(--stone); min-width: 190px; text-align: right;
}
.irr-status.bad { color: var(--error); }
.irr-new { display: flex; gap: 8px; align-items: center; }
.irr-new input {
  font-family: var(--font); font-size: 13px; padding: 7px 10px;
  border: 1px solid var(--taupe); border-radius: var(--r); width: 260px;
  background: var(--white); color: var(--charcoal);
}

.irr-page {
  /* 360px, because the tranche rows have four controls on their second line and the
     narrower column was squeezing the name box to nothing. One gap everywhere. */
  display: grid; grid-template-columns: 360px minmax(0, 1fr);
  gap: 20px; align-items: start;
}
/* TWO COLUMNS, ONE ITEM IN EACH. The right-hand side was three grid items spanning
   against a tall left column, and the grid distributed that height across the rows —
   leaving 200px of nothing between the returns and the schedule. A wrapper stacks them
   instead, and the page has no holes in it. */
.irr-inputs { grid-column: 1; grid-row: 1; }
.irr-main {
  grid-column: 2; grid-row: 1;
  display: flex; flex-direction: column; gap: 20px; min-width: 0;
}
.irr-danger { margin-top: -6px; }
@media (max-width: 1080px) {
  .irr-page { grid-template-columns: minmax(0, 1fr); }
  .irr-inputs, .irr-main { grid-column: 1; grid-row: auto; }
}

/* The answer. */
.irr-returns {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 18px 20px;
}
.irr-returns-head { margin-bottom: 14px; }
.irr-returns-head h2 { font-size: 20px; margin: 0 0 4px; }
.irr-returns-table { width: 100%; border-collapse: collapse; }
.irr-returns-table th {
  font-family: var(--font); font-size: 11px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--stone); font-weight: 500;
  padding: 0 0 6px; text-align: left; border-bottom: 1px solid var(--taupe-25);
}
.irr-returns-table th.num, .irr-returns-table td.num { text-align: right; }
.irr-returns-table td {
  padding: 9px 0; border-bottom: 1px solid var(--taupe-25); font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.irr-returns-table tr:last-child td { border-bottom: none; }
/* The line the committee is quoted. The others are the build-up to it. */
.irr-returns-table tr:last-child td { font-weight: 600; }
/* Orange, and only ever a few words on a line — this is the one thing on the page
   that says the answer above it cannot be trusted. */
.irr-warnings { margin-top: 12px; display: flex; flex-direction: column; gap: 5px; }
.irr-warnings[hidden] { display: none !important; }
.irr-warning {
  font-size: 11.5px; line-height: 1.45; color: var(--pop);
  border-left: 2px solid var(--pop); padding-left: 9px;
}

.irr-income { margin-top: 10px; }
.irr-income b { color: var(--charcoal); font-variant-numeric: tabular-nums; }

/* The inputs. */
/* ONE RHYTHM. Every card the same padding, every field the same gap, every note the
   same distance from the box it explains. It was three different values and it showed. */
.irr-inputs { display: flex; flex-direction: column; gap: 20px; }
.irr-inputs .rail-card { padding: 14px 15px; margin-bottom: 0; }
.irr-inputs .rail-card > .rail-head { margin-bottom: 12px; }
.irr-field { display: block; margin-bottom: 12px; }
.irr-field:last-child { margin-bottom: 0; }
.irr-field > span {
  display: block; font-size: 11.5px; color: var(--stone); margin-bottom: 4px;
}
.irr-field input, .irr-field select {
  width: 100%; box-sizing: border-box; font-family: var(--font); font-size: 13px;
  padding: 6px 8px; border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal);
}
.irr-field input:focus, .irr-field select:focus {
  outline: none; border-color: var(--slate);
}
/* A select left to the browser renders as a small grey pill that matches nothing else on
   the card. Its own chevron, drawn in the palette, and the native one removed — otherwise
   both appear. */
.irr-field select {
  appearance: none; -webkit-appearance: none; padding-right: 26px; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%237E7F7F' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center;
}
.irr-field select:disabled {
  background-color: var(--taupe-15); color: var(--stone); cursor: default;
}
.irr-note {
  display: block; font-size: 10.5px; color: var(--stone); font-style: normal;
  margin-top: 5px; line-height: 1.45;
}

.irr-rows { display: flex; flex-direction: column; gap: 8px; }
.irr-row { display: grid; gap: 6px; align-items: center; }
.irr-row-tier { grid-template-columns: 1fr 1fr 1fr 18px; }
.irr-row-backend { grid-template-columns: 1fr 86px 44px 66px 18px; }
.irr-row-head {
  grid-template-columns: 1fr 1fr 1fr 18px;
  font-size: 10.5px; color: var(--stone); letter-spacing: .02em;
}

/* A TRANCHE IS TWO LINES. Seven controls do not fit across a rail, and the version that
   tried made the name box a few pixels wide and pushed the date control out of its card. */
.irr-tranche {
  border: 1px solid var(--taupe-25); border-radius: var(--r); padding: 9px 10px;
  background: var(--taupe-15);
}
.irr-tranche-top {
  display: grid; grid-template-columns: 1fr 100px 50px 16px; gap: 6px;
  align-items: end;
}
.irr-tranche-bottom {
  display: grid; grid-template-columns: 1.3fr .55fr .85fr; gap: 6px; margin-top: 8px;
}
.irr-warrant-top {
  display: grid; grid-template-columns: 1.1fr 1fr .5fr 16px; gap: 6px; align-items: end;
}
/* The remove cross sits on the baseline of the fields beside it rather than floating
   above them, which it did when its label was blank. */
.irr-tranche-top .irr-mini .irr-remove { padding: 4px 0; }
.irr-tranche select {
  width: 100%; box-sizing: border-box; font-family: var(--font); font-size: 12px;
  padding: 5px 6px; border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal);
}
.irr-tranche select:focus { outline: none; border-color: var(--slate); }
.irr-mini { display: block; min-width: 0; }
.irr-mini > span {
  display: block; font-size: 10px; color: var(--stone); margin-bottom: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.irr-tranche input[type="text"], .irr-tranche input[type="number"],
.irr-tranche input[type="date"] {
  width: 100%; box-sizing: border-box; font-family: var(--font); font-size: 12px;
  padding: 5px 6px; border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal);
}
.irr-tranche input:focus { outline: none; border-color: var(--slate); }
.irr-tranche input[type="checkbox"] { width: auto; margin: 0; }
.irr-row input[type="text"], .irr-row input[type="number"], .irr-row select {
  width: 100%; box-sizing: border-box; font-family: var(--font); font-size: 12px;
  padding: 5px 6px; border: 1px solid var(--taupe); border-radius: var(--r);
  background: var(--white); color: var(--charcoal);
}
.irr-row input:focus, .irr-row select:focus { outline: none; border-color: var(--slate); }
.irr-row input[type="checkbox"] { margin: 0; }
.irr-remove {
  background: none; border: 0; padding: 0; cursor: pointer; line-height: 1;
  color: var(--stone); font-size: 15px;
}
.irr-remove:hover { color: var(--error); }
.irr-total {
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--taupe-25);
  color: var(--stone);
}
.irr-total b { color: var(--charcoal); font-variant-numeric: tabular-nums; }

/* The working. */
.irr-schedule {
  background: var(--white); border: 1px solid var(--taupe); border-radius: var(--r);
  padding: 18px 20px;
}
.irr-schedule-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin-bottom: 12px;
}
.irr-schedule-head h4 {
  margin: 0; font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stone); font-weight: 500;
}
/* The repayment profile, beside the schedule's heading. The one line that stops somebody
   concluding a facility does not amortise because its first instalment is on row 25. */
.irr-profile {
  flex: 1; font-size: 11.5px; color: var(--charcoal); min-width: 260px;
}
/* Which scenario the note quotes. Slate rather than a colour, per the design language —
   this says "this one", not "this one is good". */
.irr-active-tag {
  display: inline-block; font-size: 10px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; padding: 2px 6px; margin-left: 6px;
  border: 1px solid var(--slate); color: var(--slate); background: var(--white);
  vertical-align: middle;
}
tr.is-active > td { background: var(--taupe-15); }
.irr-build { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.irr-build label { display: flex; align-items: center; gap: 4px; color: var(--stone); }
.irr-build input[type="number"] {
  width: 54px; font-family: var(--font); font-size: 12px; padding: 4px 5px;
  border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white);
  color: var(--charcoal);
}

/* Horizontally scrolling on its own, never the page: thirteen columns of numbers
   will not fit a laptop, and a page that scrolls sideways is broken. */
.irr-grid-wrap { overflow-x: auto; max-height: 560px; overflow-y: auto; }
.irr-grid { width: 100%; border-collapse: collapse; font-size: 12px; }
.irr-grid th {
  position: sticky; top: 0; z-index: 2; background: var(--taupe-15);
  font-family: var(--font); font-size: 10.5px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--stone); font-weight: 500;
  padding: 7px 8px; text-align: left; white-space: nowrap;
  border-bottom: 1px solid var(--taupe);
}
.irr-grid th.num { text-align: right; }
.irr-grid td {
  padding: 3px 8px; border-bottom: 1px solid var(--taupe-25); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.irr-grid td.num { text-align: right; }
.irr-grid td.strong { font-weight: 600; }
/* A month where nothing happens is still worth seeing — it is the evidence that the
   facility is sitting there — but it should not compete with the months that do. */
.irr-grid tr.is-quiet td { color: var(--stone); }
.irr-grid tr:hover td { background: #FAFAF8; }
.irr-cell { padding: 1px 4px !important; }
.irr-cell input {
  width: 104px; box-sizing: border-box; text-align: right; font-family: var(--font);
  font-size: 12px; font-variant-numeric: tabular-nums; padding: 3px 5px;
  border: 1px solid transparent; border-radius: var(--r); background: transparent;
  color: var(--charcoal);
}
.irr-cell input:hover { border-color: var(--taupe-25); background: var(--white); }
.irr-cell input:focus {
  outline: none; border-color: var(--slate); background: var(--white);
}
.irr-cell input:disabled { border-color: transparent; background: transparent; }

/* A month somebody set by hand. Marked, because the rest of the schedule moves when the
   term or the amortisation changes and these do not — and a row that ignores an input is
   one people should be able to see rather than discover. */
.irr-grid tr.is-override td { background: #FBF7EF; }
.irr-grid tr.is-override td:first-child { box-shadow: inset 2px 0 0 var(--pop); }
.irr-grid tr.is-override:hover td { background: #F7F2E7; }

/* Money boxes are text inputs, so they can carry thousands separators — see the note at
   the top of irr.js. Tabular figures so columns of them line up. */
.irr-money, .irr-row input.irr-money {
  font-variant-numeric: tabular-nums; text-align: right;
}
.irr-field input[type="number"], .irr-row input[type="number"] {
  font-variant-numeric: tabular-nums;
}
.irr-note.is-on { color: var(--slate); font-weight: 500; }

/* A segmented control: two answers, both readable without opening anything. */
.irr-choice { display: flex; gap: 0; }
.irr-choice button {
  flex: 1; font-family: var(--font); font-size: 11.5px; line-height: 1.25;
  padding: 6px 7px; cursor: pointer; background: var(--white);
  border: 1px solid var(--taupe); color: var(--stone);
}
.irr-choice button:first-child { border-radius: var(--r) 0 0 var(--r); }
.irr-choice button:last-child { border-radius: 0 var(--r) var(--r) 0; border-left: none; }
.irr-choice button:hover { color: var(--charcoal); }
.irr-choice button.is-on {
  background: var(--slate); border-color: var(--slate); color: #fff;
}
.irr-choice button.is-on + button { border-left: none; }
