/* Boxd back office.
   Brand: #0B0C10 ground, #0A99FA accent, IBM Plex Sans / Mono.
   No framework and no build step — the API serves these three files directly. */

:root {
  /* Light is the default, and it is the default deliberately rather than by
     inheritance from an operating system. Most of the people this is for open
     it beside an accountant's screen in daylight; a dark back office reads as a
     developer tool, which is the one thing this is trying not to be.

     Dark is a choice, kept one click away in the top bar and remembered per
     browser. Nothing here follows prefers-color-scheme: a customer who has
     their laptop in dark mode has said something about their editor, not about
     where they want to read a trial balance. */
  --bg: #FFFFFF;
  --card: #FFFFFF;
  --card-2: #F7F8FA;
  --rule: #E3E6EA;
  --rule-soft: #EDEFF2;
  --accent: #0A7FD4;        /* a step darker than the brand blue: #0A99FA on
                               white is 2.6:1, which fails on text */
  --accent-dim: #0A7FD414;
  --white: #0B0C10;         /* the "strongest text" token. The name is wrong in
                               light mode and renaming it would touch 200 rules
                               in five files, so it means emphasis, not white. */
  --body: #33393F;
  --dim: #5C646D;
  --muted: #6E7681;
  --ok: #17865C;
  --warn: #9A6410;
  --stop: #C0392F;
  --on-accent: #FFFFFF;
  --shadow: 0 1px 2px rgba(11,12,16,.06), 0 1px 3px rgba(11,12,16,.04);

  --r: 10px;
  --sans: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

/* The original palette, now behind a switch. */
:root[data-theme="dark"] {
  --bg: #0B0C10;
  --card: #12151A;
  --card-2: #0E1419;
  --rule: #232830;
  --rule-soft: #1A1E25;
  --accent: #0A99FA;
  --accent-dim: #0A99FA22;
  --white: #FFFFFF;
  --body: #C8CCD2;
  --dim: #8A9199;
  --muted: #6E7681;
  --ok: #35C08A;
  --warn: #E5A83B;
  --stop: #E5544B;
  --on-accent: #04121F;
  --shadow: none;
}

* { box-sizing: border-box; }

/* The UA rule for [hidden] is display:none at the lowest specificity, so any
   class that sets display — .signin is a grid — silently defeats it and leaves
   two screens stacked on top of each other. Stated once here rather than
   remembered at every call site. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--body);
  font: 400 14px/1.5 var(--sans);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { color: var(--white); font-weight: 600; letter-spacing: -0.01em; }
h2 { font-size: 14px; margin: 0 0 14px; }
code, .mono { font-family: var(--mono); }
button { font: inherit; cursor: pointer; }

/* ── brand ─────────────────────────────────────────────── */
.brand { display: flex; align-items: center; gap: 9px; }
.mark {
  width: 18px; height: 18px; border: 1.5px solid var(--white);
  border-radius: 4px; position: relative; flex: none;
}
.mark::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
}
.wordmark {
  color: var(--white); font-weight: 600; font-size: 17px;
  letter-spacing: -0.03em;
}

/* ── sign in ───────────────────────────────────────────── */
.signin {
  min-height: 100dvh; display: grid; place-items: center; padding: 24px;
}
.signin-card {
  width: 100%; max-width: 380px; background: var(--card);
  border: 1px solid var(--rule); border-radius: 14px; padding: 28px;
}
.signin-lede { color: var(--dim); margin: 20px 0 16px; font-size: 13px; }
/* Stacked rather than side by side: two fields and a button in a row is a
   phone-width problem waiting to happen, and nobody minds a tall sign-in box. */
.signin-card form { display: flex; flex-direction: column; gap: 8px; }
.signin-card button { width: 100%; }

.providers { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.providers::before {
  content: "or"; color: var(--muted); font-size: 12px; text-align: center;
  margin: 2px 0;
}
.provider-btn {
  width: 100%; padding: 10px 14px; border-radius: var(--r);
  border: 1px solid var(--rule); background: var(--card-2); color: var(--body);
  font: inherit; text-align: center;
}
.provider-btn:hover { border-color: var(--accent); color: var(--white); }

.signin-alt { margin-top: 20px; border-top: 1px solid var(--rule-soft); padding-top: 14px; }
.signin-alt summary {
  color: var(--muted); font-size: 12px; cursor: pointer; list-style: none;
}
.signin-alt summary::-webkit-details-marker { display: none; }
.signin-alt summary:hover { color: var(--body); }
.signin-alt form { margin-top: 12px; }
.signin-card input {
  flex: 1; min-width: 0; background: var(--bg); border: 1px solid var(--rule);
  border-radius: var(--r); color: var(--white); padding: 10px 12px;
  font-family: var(--mono); font-size: 13px;
}
.signin-card input:focus { outline: none; border-color: var(--accent); }
.signin-card button {
  background: var(--accent); color: var(--on-accent); border: 0; border-radius: var(--r);
  padding: 10px 16px; font-weight: 600;
}
.signin-error { color: var(--stop); font-size: 13px; margin: 12px 0 0; }
.signin-note { color: var(--muted); font-size: 12px; margin: 16px 0 0; line-height: 1.55; }

/* ── chrome ────────────────────────────────────────────── */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 22px; border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; background: var(--bg);
  backdrop-filter: blur(8px); z-index: 20;
}
.topbar-meta { display: flex; align-items: center; gap: 14px; font-size: 13px; }
.tenant { color: var(--white); font-weight: 500; }
.user { color: var(--muted); }

/* Only visible for somebody who works for more than one company. Deliberately
   quiet: it sits beside the company name rather than replacing it, so the
   answer to "whose books am I looking at" is still readable at a glance from
   across a desk, which is the question this control exists to keep answerable. */
.company-switch {
  background: var(--card-2); color: var(--white);
  border: 1px solid var(--rule); border-radius: 6px;
  padding: 3px 8px; font: inherit; font-size: 13px; max-width: 220px;
}
.company-switch:hover { border-color: var(--dim); }

/* A panel inside a panel, for a form that only appears when asked for. */
.sub-panel {
  margin-top: 14px; padding: 14px;
  background: var(--card-2); border: 1px solid var(--rule-soft); border-radius: var(--r);
}

/* One bank account. The consent line is the reason this exists as its own block
   rather than a table row: it expires while nobody is looking, and it needs
   room to say so in a sentence. */
.bank-row {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 12px 0; border-bottom: 1px solid var(--rule-soft);
}
.bank-row:last-child { border-bottom: 0; }
.bank-row .bank-name { color: var(--white); font-weight: 500; }
.bank-row .bank-hint { color: var(--muted); font-family: var(--mono); font-size: 12px; }
.bank-row .bank-when { color: var(--dim); font-size: 13px; margin-left: auto; }
.bank-row.is-stale { border-left: 2px solid var(--warn); padding-left: 10px; }
.bank-consent { color: var(--warn); font-size: 13px; }
.bank-consent.is-gone { color: var(--stop); }
.link-btn {
  background: none; border: 0; color: var(--dim); padding: 4px 0;
  font-size: 13px; text-decoration: underline; text-underline-offset: 3px;
}
.link-btn:hover { color: var(--white); }

/* ── the shell ─────────────────────────────────────────────
   A column of sections down the left, the way the deck has drawn it since the
   first version, and the way every back office the customer already uses is
   laid out. The row of tabs it replaces could hold about eight before it wrapped
   onto a second line, and it was holding twelve.

   Grid rather than a fixed-position aside, so the main column cannot slide
   under the nav at a narrow width — which is what a fixed sidebar does on the
   laptop most of these people actually own. */
.shell { display: grid; grid-template-columns: 216px minmax(0, 1fr); align-items: start; }

main { padding: 0 26px 64px; max-width: 1180px; margin: 0; min-width: 0; }

@media (max-width: 900px) {
  /* Below this the sidebar becomes a scrolling strip across the top. A 216px
     column on a phone leaves 150px for a balance sheet. */
  .shell { grid-template-columns: 1fr; }
  .sidenav {
    position: static; height: auto; border-right: 0;
    border-bottom: 1px solid var(--rule);
    display: flex; gap: 4px; overflow-x: auto; padding: 10px 14px;
  }
  .navgroup { display: contents; }
  .navgroup-h { display: none; }
  .tab { white-space: nowrap; }
  main { padding: 0 16px 64px; }
}

/* ── KPI strip ─────────────────────────────────────────── */
.kpis {
  display: grid; gap: 1px; background: var(--rule);
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  border-bottom: 1px solid var(--rule);
}
.kpi { background: var(--bg); padding: 18px 22px; }
.card, .panel { box-shadow: var(--shadow); }
.kpi-label {
  color: var(--muted); font-size: 11px; text-transform: uppercase;
  letter-spacing: .07em; margin-bottom: 7px;
}
.kpi-value {
  color: var(--white); font: 500 24px/1.1 var(--mono); letter-spacing: -0.02em;
}
.kpi-value.is-accent { color: var(--accent); }
.kpi-value.is-ok { color: var(--ok); }
.kpi-value.is-stop { color: var(--stop); }
.kpi-sub { color: var(--muted); font-size: 12px; margin-top: 6px; }

/* ── the sections ──────────────────────────────────────────
   Grouped, because twelve flat items is a list somebody reads left to right
   looking for the one they want. Six groups of two is a thing somebody learns
   the shape of once and then aims at.

   The class is still `.tab`. The markup moved from a row to a column and the
   role went with it, but `scripts/ui-check.mjs` addresses these in
   thirty-eight places as `.tab[data-view="…"]`, and a rename would have been a
   morning of updating selectors to describe the same button. */
.sidenav {
  position: sticky; top: 61px; align-self: start;
  height: calc(100vh - 61px); overflow-y: auto;
  padding: 18px 12px 24px; border-right: 1px solid var(--rule);
  background: var(--card-2);
}
.navgroup { margin-bottom: 18px; }
.navgroup:last-child { margin-bottom: 0; }
.navgroup-h {
  margin: 0 0 6px; padding: 0 10px;
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--muted); font-weight: 600;
}
.tab {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: none; border: 0; border-radius: 7px;
  padding: 7px 10px; margin-bottom: 1px;
  color: var(--dim); font-size: 13.5px; text-align: left;
}
.tab:hover { background: var(--accent-dim); color: var(--white); }
.tab.is-active {
  background: var(--accent-dim); color: var(--accent); font-weight: 600;
}
.tab .pill { margin-left: auto; }

/* The one control that is not a section. Beside the sign-out, because that is
   where a person looks for "things about me rather than about the company". */
.theme-toggle {
  background: none; border: 1px solid var(--rule); border-radius: 999px;
  color: var(--dim); padding: 4px 11px; font-size: 12.5px; line-height: 1.5;
}
.theme-toggle:hover { color: var(--white); border-color: var(--dim); }

/* Views are swapped by toggling [hidden], which is a cut: one screen is gone
   and the next is fully painted in the same frame. On a recording that reads as
   a jump, and in use it loses the sense that you moved rather than the page
   changed underneath you.
   An animation rather than a transition, because a transition cannot run on
   display:none → block. It re-runs each time the element is shown, which is
   exactly the moment worth softening. */
@keyframes viewIn {
  from { opacity: 0; transform: translateY(6px) }
  to   { opacity: 1; transform: none }
}
.view { padding-top: 22px; }
.view:not([hidden]) { animation: viewIn .22s cubic-bezier(.2,.6,.2,1) both; }

/* Somebody who has asked their operating system to stop moving things gets no
   movement. The screens still change; they just do not slide. */
@media (prefers-reduced-motion: reduce) {
  .view:not([hidden]) { animation: none; }
}
.view-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 16px; flex-wrap: wrap;
}
.filters { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  background: var(--card); border: 1px solid var(--rule); border-radius: 999px;
  color: var(--dim); padding: 5px 13px; font-size: 12.5px;
}
.chip.is-active { color: var(--white); border-color: var(--accent); background: var(--accent-dim); }

/* ── proposal cards ────────────────────────────────────── */
.cards { display: grid; gap: 12px; }
.card {
  background: var(--card); border: 1px solid var(--rule); border-radius: 12px;
  overflow: hidden;
}
.card-head {
  display: grid; grid-template-columns: 1fr auto; gap: 14px;
  padding: 16px 18px; align-items: start;
}
.card-title { color: var(--white); font-weight: 500; font-size: 15px; }
.card-sub { color: var(--muted); font-size: 12.5px; margin-top: 4px; }
.card-amount {
  font: 500 17px/1.2 var(--mono); color: var(--white); text-align: right; white-space: nowrap;
}
.card-amount.is-in { color: var(--ok); }

.badges { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.badge {
  font: 500 11px/1.6 var(--sans); padding: 1px 8px; border-radius: 5px;
  border: 1px solid var(--rule); color: var(--dim); background: var(--card-2);
}
.badge.risk-auto    { color: var(--ok);   border-color: #35C08A44; }
.badge.risk-review  { color: var(--warn); border-color: #E5A83B44; }
.badge.risk-blocked { color: var(--stop); border-color: #E5544B44; }
.badge.mono { font-family: var(--mono); }

.rationale {
  padding: 0 18px 14px; color: var(--body); font-size: 13.5px; line-height: 1.6;
}
.rationale b { color: var(--dim); font-weight: 500; }

/* the posting preview — the thing that makes one-tap approval defensible */
.posting { border-top: 1px solid var(--rule-soft); background: var(--card-2); overflow-x: auto; }
.posting table {
  width: 100%; min-width: 420px; border-collapse: collapse;
  font-family: var(--mono); font-size: 12.5px;
}
/* The code column sizes to its content so the account name starts next to it
   rather than across an empty half of the card. */
.posting th:first-child, .posting td:first-child { width: 1%; white-space: nowrap; }
.posting th {
  text-align: left; color: var(--muted); font: 500 10.5px/1.6 var(--sans);
  text-transform: uppercase; letter-spacing: .06em; padding: 9px 18px;
  border-bottom: 1px solid var(--rule-soft);
}
.posting td { padding: 8px 18px; color: var(--body); border-bottom: 1px solid var(--rule-soft); }
.posting tr:last-child td { border-bottom: 0; }
.posting .num { text-align: right; white-space: nowrap; }
.posting .code { color: var(--accent); }
.posting .name { font-family: var(--sans); color: var(--body); }

.card-actions {
  display: flex; gap: 8px; padding: 14px 18px; border-top: 1px solid var(--rule-soft);
  align-items: center; flex-wrap: wrap;
}
.btn {
  background: var(--accent); color: var(--on-accent); border: 0; border-radius: 8px;
  padding: 9px 18px; font-weight: 600; font-size: 13.5px;
}
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn-ghost {
  background: transparent; color: var(--body); border: 1px solid var(--rule);
  border-radius: 8px; padding: 9px 16px; font-size: 13.5px;
}
.btn-ghost:hover:not(:disabled) { border-color: var(--dim); color: var(--white); }
.btn-ghost:disabled { opacity: .45; cursor: not-allowed; }
.reject-form { border-top: 1px solid var(--rule-soft); }
.reject-form input {
  flex: 1; min-width: 200px; background: var(--bg); border: 1px solid var(--rule);
  border-radius: 8px; color: var(--white); padding: 9px 12px; font: 400 13.5px var(--sans);
}
.reject-form input:focus { outline: none; border-color: var(--accent); }

.action-note { color: var(--muted); font-size: 12.5px; margin-left: auto; max-width: 62ch; }
/* When the note is the whole row there is nothing to sit beside, so it reads
   from the left like every other line in the card. */
.card-actions > .action-note:only-child { margin-left: 0; }
.action-note.is-stop { color: var(--stop); }

/* ── panels and tables ─────────────────────────────────── */
/* minmax(0, …) rather than 1fr: a grid track's automatic minimum is its content,
   so a wide table stops the panel shrinking and pushes it past the edge of the
   page instead of scrolling inside its own .table-wrap. */
.split {
  display: grid; gap: 16px; align-items: start;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
@media (max-width: 900px) { .split { grid-template-columns: minmax(0, 1fr); } }

.panel {
  background: var(--card); border: 1px solid var(--rule);
  border-radius: 12px; padding: 18px;
}
/* The note under a panel heading.
   The top margin was -8px, which was right when every .panel-head was a single
   line of text on a baseline. The invoices head is a row of chips and a search
   box, so the negative pull dragged "What customers still owe…" up into the
   buttons and the two overlapped. The head now owns the gap below it, which is
   where that decision belongs, and this owns none of it. */
.panel-note { color: var(--muted); font-size: 12.5px; margin: 0 0 16px; line-height: 1.6; max-width: 62ch; }
.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13px; }
table.data th {
  text-align: left; color: var(--muted); font: 500 10.5px/1.6 var(--sans);
  text-transform: uppercase; letter-spacing: .06em; padding: 8px 10px;
  border-bottom: 1px solid var(--rule); white-space: nowrap;
}
table.data td { padding: 9px 10px; border-bottom: 1px solid var(--rule-soft); }
table.data tr:last-child td { border-bottom: 0; }
table.data td.num, table.data th.num { text-align: right; font-family: var(--mono); white-space: nowrap; }
table.data td.code { font-family: var(--mono); color: var(--accent); }
table.data tfoot td { border-top: 1px solid var(--rule); font-weight: 600; color: var(--white); }
table.data td.muted { color: var(--muted); }
table.data td.pos { color: var(--ok); }
table.data td.neg { color: var(--stop); }

/* A statement is a set of sections, not a flat list. The section row carries its
   own subtotal so the eye can stop at the level it needs. */
table.data tr.row-section td {
  padding-top: 18px; color: var(--white); font-weight: 600;
  border-bottom: 1px solid var(--rule);
}
table.data tr.row-section:first-child td { padding-top: 4px; }
/* Retained earnings has no account code and cannot be posted to; it reads as a
   derived line rather than another account in the list. */
table.data tr.is-computed td { color: var(--dim); font-style: italic; }

.inline-check {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--dim); font-size: 12.5px; white-space: nowrap;
}
.inline-check input { accent-color: var(--accent); }

.feed { display: grid; gap: 0; }
.feed-row {
  display: grid; grid-template-columns: 84px 1fr auto; gap: 14px;
  padding: 11px 0; border-bottom: 1px solid var(--rule-soft); align-items: baseline;
}
.feed-row:last-child { border-bottom: 0; }
.feed-time { color: var(--muted); font: 400 12px/1.5 var(--mono); }
.feed-what { color: var(--body); }
.feed-what .who { color: var(--white); }
.feed-what .act { font-family: var(--mono); font-size: 12.5px; color: var(--accent); }
.feed-kind { color: var(--muted); font-size: 12px; }

/* ── import ────────────────────────────────────────────── */
.dropzone {
  display: grid; place-items: center; padding: 34px; text-align: center;
  border: 1px dashed var(--rule); border-radius: 12px; color: var(--dim);
  cursor: pointer; background: var(--card-2);
}
.dropzone.is-over { border-color: var(--accent); color: var(--white); }
.import-actions { display: flex; gap: 10px; align-items: end; margin-top: 14px; flex-wrap: wrap; }
.field { display: grid; gap: 6px; color: var(--muted); font-size: 12px; }
.field select {
  background: var(--bg); border: 1px solid var(--rule); border-radius: 8px;
  color: var(--white); padding: 8px 10px; font: 400 13px var(--sans); min-width: 220px;
}
.result { margin-top: 18px; border-top: 1px solid var(--rule); padding-top: 16px; }
.result-figures { display: flex; gap: 22px; flex-wrap: wrap; margin-bottom: 12px; }
.result-figures div { color: var(--muted); font-size: 12px; }
.result-figures b { display: block; color: var(--white); font: 500 20px/1.3 var(--mono); }
.result ul { margin: 8px 0 0; padding-left: 18px; color: var(--dim); font-size: 12.5px; }

.empty { color: var(--muted); padding: 40px 0; text-align: center; font-size: 13.5px; }
.empty b { display: block; color: var(--body); margin-bottom: 6px; font-weight: 500; }

/* ── toast ─────────────────────────────────────────────── */
.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  background: var(--card); border: 1px solid var(--rule); color: var(--white);
  border-radius: 10px; padding: 11px 18px; font-size: 13.5px; z-index: 60;
  box-shadow: 0 12px 40px rgba(0,0,0,.55); max-width: min(560px, calc(100vw - 32px));
}
.toast.is-stop { border-color: #E5544B66; }

/* ── phone ─────────────────────────────────────────────── */
/* This is the screen the product is actually approved on — someone clearing the
   queue between meetings. Everything below assumes a thumb and one hand. */
@media (max-width: 620px) {
  main, .tabs, .topbar { padding-left: 14px; padding-right: 14px; }

  /* Which company, and a way out. The user's own name and role are not worth a
     line of a phone screen. */
  .user { display: none; }
  .company-switch { max-width: 38vw; }
  .tenant { max-width: 46vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  .kpi { padding: 14px; }
  .kpi-value { font-size: 20px; }

  /* nowrap matters here. The base rule wraps, which is right for a row; on a
     column it means flexbox spills into a SECOND COLUMN when the content is
     taller than the line, and then stretches each child to its own column's
     width rather than the container's. The result is a page that scrolls
     sideways for no visible reason. */
  .view-head { flex-direction: column; flex-wrap: nowrap; align-items: stretch; }
  /* min-width: 0 as well as overflow-x. A flex item's automatic minimum is its
     content, so without it the row of chips refuses to shrink and pushes the
     whole page sideways instead of scrolling inside its own strip. Same trap as
     the 1fr grid tracks elsewhere in this file. */
  .filters { flex-wrap: nowrap; overflow-x: auto; min-width: 0; padding-bottom: 2px; }
  .chip { flex: none; }
  #refresh-queue { align-self: flex-start; }

  /* The posting reflows into one row per line instead of scrolling sideways.
     Someone approving on a phone has to be able to see both sides of the entry
     without moving the page — that is the whole reason the preview is there. */
  .posting { overflow-x: visible; }
  .posting table, .posting tbody { display: block; min-width: 0; }
  .posting thead { display: none; }
  .posting tr {
    /* minmax(0, 1fr), not 1fr: a grid track's automatic minimum is its content,
       so a long account name refuses to shrink and shoves the amount off the
       right edge of the phone instead of wrapping. */
    display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 2px 10px;
    padding: 11px 14px; border-bottom: 1px solid var(--rule-soft);
    align-items: baseline;
  }
  .posting tr:last-child { border-bottom: 0; }
  .posting td { display: block; padding: 0; border: 0; }
  .posting td.is-empty { display: none; }
  .posting td.num { grid-column: 3; }
  /* The column headings are gone, so each amount says which side it is on. */
  .posting td.dr::before { content: "Dr "; color: var(--muted); }
  .posting td.cr::before { content: "Cr "; color: var(--muted); }

  /* Amount first. On a phone the question is "how much" before "what", and the
     two-column head clipped the currency off the right edge. */
  .card-head { padding: 14px; grid-template-columns: 1fr; gap: 4px; }
  .card-amount { text-align: left; order: -1; font-size: 20px; }
  .card-title { font-size: 15.5px; }

  .rationale, .card-actions { padding-left: 14px; padding-right: 14px; }

  /* On a phone the P&L has to fit the account name, the amount and the prior
     year. The account code is the one column whose information is also carried
     by the column next to it, so it is the one that goes. Statements only —
     the entry list's first column is a date and is not expendable. */
  table.data.stmt tr > *:first-child { display: none; }
  .inline-check { margin-top: 4px; }

  .btn, .btn-ghost { flex: 1; min-height: 44px; }

  .ask-actions .btn { flex: none; }
  .action-note { margin-left: 0; width: 100%; }
  .field select { min-width: 0; width: 100%; }
  .import-actions { display: grid; grid-template-columns: 1fr 1fr; }
  .import-actions .field { grid-column: 1 / -1; }
}

/* ── what this workspace has ───────────────────────────────── */
/* Its own screen. Which skills a company has is no longer one of these
   switches — that is our decision now — so what is left here is the half a
   company does decide: which parts of the product it has. */
.feature-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--rule);
}
.feature-row:last-child { border-bottom: none; }
.feature-name { color: var(--white); font-weight: 500; }
.feature-sub { color: var(--muted); font-size: 12.5px; margin-top: 3px; max-width: 74ch; }
/* Why the button cannot do anything. Said in the row rather than only in the
   refusal, so nobody presses it to find out. */
.feature-blocked { color: var(--dim); font-size: 12px; margin-top: 5px; }
.feature-switch { flex: none; }
.feature-switch .btn-ghost { min-width: 62px; }
.feature-switch .btn-ghost.is-on { color: var(--ok); border-color: #35C08A55; }
.feature-switch .btn-ghost[disabled] { opacity: .5; cursor: not-allowed; }

/* ── asking for something ──────────────────────────────────── */
.badge.kind-operating { color: var(--accent); border-color: #0A99FA55; background: var(--accent-dim); }
.badge.kind-advisory  { color: var(--dim);    border-color: var(--rule); }

.ask textarea {
  width: 100%; box-sizing: border-box; resize: vertical;
  background: var(--bg); border: 1px solid var(--rule); border-radius: 10px;
  color: var(--white); padding: 11px 13px; font: 400 14px/1.5 var(--sans);
}
.ask textarea:focus { outline: none; border-color: var(--accent); }
.ask-actions { display: flex; align-items: center; gap: 12px; margin-top: 10px; }

.request-row { padding: 13px 0; border-bottom: 1px solid var(--rule); }
.request-row:last-child { border-bottom: none; }
.request-ask { color: var(--white); font-weight: 500; max-width: 78ch; }
/* What was done, one line each. The badge carries the difference between a part
   that was answered and a part that was not, because that difference is the
   whole reason this row is on the screen. */
.request-did { color: var(--muted); font-size: 12.5px; margin-top: 6px; max-width: 78ch; }
.request-unmet { color: var(--dim); }
.request-detail { color: var(--dim); font-size: 12px; margin-top: 6px; max-width: 78ch; }


/* ── access ─────────────────────────────────────────────── */
.sub-head { font-size: 13px; margin: 26px 0 10px; color: var(--white); }
.invite-form { display: grid; grid-template-columns: minmax(0,1fr) auto auto; gap: 8px; }
@media (max-width: 720px) { .invite-form { grid-template-columns: minmax(0,1fr); } }
.invite-form input, .invite-form select {
  padding: 9px 12px; border-radius: var(--r); border: 1px solid var(--rule);
  background: var(--card-2); color: var(--body); font: inherit; min-width: 0;
}
.invite-form button {
  padding: 9px 16px; border-radius: var(--r); border: 0;
  background: var(--accent); color: var(--on-accent); font-weight: 600;
}
.note-inline {
  margin-top: 12px; padding: 12px 14px; border-radius: var(--r);
  background: var(--card-2); border-left: 3px solid var(--accent);
  font-size: 13px; line-height: 1.6; word-break: break-all;
}
.note-inline b { color: var(--white); font-weight: 600; }
.pill-role {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em;
  text-transform: uppercase; color: var(--dim);
}
.you { color: var(--accent); font-size: 11px; margin-left: 6px; }
.muted-row td { color: var(--muted); }

/* ── moving in ──────────────────────────────────────────────────────────────
   The changeover screen. It is a sequence rather than a dashboard, so the
   emphasis is on what is still in the way: an unmapped line is tinted, a line
   deliberately left out is dimmed, and both stay visible after the commit
   because the reconciliation is the record. */
.onb-form {
  display: grid; grid-template-columns: minmax(0,1fr) auto auto auto;
  gap: 10px; align-items: end; margin-top: 14px;
}
@media (max-width: 860px) { .onb-form { grid-template-columns: minmax(0,1fr); } }
.onb-form input {
  padding: 9px 12px; border-radius: var(--r); border: 1px solid var(--rule);
  background: var(--card-2); color: var(--body); font: inherit; min-width: 0;
}
.onb-form button {
  padding: 9px 18px; border-radius: var(--r); border: 0;
  background: var(--accent); color: var(--on-accent); font-weight: 600;
}

.onb-summary { display: flex; gap: 28px; flex-wrap: wrap; margin: 16px 0 4px; }
.onb-stat-value {
  font: 600 20px var(--sans); color: var(--white); font-variant-numeric: tabular-nums;
}
.onb-stat-label { color: var(--muted); font-size: 12px; margin-top: 2px; }

.note-inline.stop { border-left-color: var(--stop); }

table.data tr.is-unmapped td { background: #E5544B0F; }
table.data tr.is-muted td { color: var(--muted); }
select.onb-map {
  background: var(--bg); border: 1px solid var(--rule); border-radius: 8px;
  color: var(--white); padding: 6px 8px; font: 400 12.5px var(--sans);
  max-width: 260px;
}
select.onb-map + .link-btn { margin-left: 10px; }

/* ── the document behind an entry ─────────────────────────────
   Two things sit here and only one of them is the picture. The checks are what
   decide the approval — the tax on the document against the treatment chosen,
   anything already in the books at the same amount — so they read first, as
   sentences, above the evidence rather than under it. */

.evidence {
  margin: 14px 0 2px; padding-top: 12px; border-top: 1px solid var(--rule-soft);
}
.evidence-loading { color: var(--muted); font-size: 12.5px; }

.check {
  display: flex; gap: 9px; align-items: flex-start;
  margin-bottom: 7px; font-size: 13px; line-height: 1.5;
}
.check-mark {
  flex: 0 0 auto; width: 17px; height: 17px; margin-top: 1px;
  border-radius: 50%; display: grid; place-items: center;
  font: 600 11px/1 var(--sans);
  background: #E5A83B22; color: var(--warn);
}
.check.is-ok .check-mark { background: #35C08A1F; color: var(--ok); }
.check-duplicate .check-mark { background: #E5544B22; color: var(--stop); }
.check-note { color: var(--body); }

.evidence-file { display: inline-block; margin-top: 8px; }
.evidence-image {
  max-width: 340px; max-height: 320px; border-radius: var(--r);
  border: 1px solid var(--rule); display: block;
  /* Receipts are photographed against whatever the desk is. A light backing
     stops a pale slip disappearing into a dark interface. */
  background: #F4F6F8;
}
.evidence-pdf {
  display: inline-block; padding: 9px 14px; border-radius: var(--r);
  border: 1px solid var(--rule); background: var(--card-2);
  color: var(--accent); font-size: 13px;
}
.evidence-pdf::before { content: "◫"; margin-right: 8px; opacity: .8; }
.evidence-file:hover .evidence-pdf { border-color: var(--accent); }

@media (max-width: 560px) {
  .evidence-image { max-width: 100%; }
}

/* ── invoices ──────────────────────────────────────────────── */
/* center rather than baseline: one side is chips and a search field, the other
   is buttons, and baseline-aligning two rows of controls of different heights
   is what made this row look like it had been dropped rather than laid out. */
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.panel-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 14px; }
.form-row { display: flex; flex-wrap: wrap; gap: 14px; margin: 12px 0 18px; }
.form-row label { display: flex; flex-direction: column; gap: 4px; font-size: 12px;
  color: var(--muted); }
.form-row label.check { flex-direction: row; align-items: center; gap: 6px; }
/* A settings panel that runs on for two screens needs somewhere for the eye to
   stop. These are the seams between "who you are" and "how this works". */
.form-heading {
  font-size: 13px; font-weight: 600; color: var(--white);
  margin: 26px 0 4px; padding-top: 18px; border-top: 1px solid var(--rule);
}
/* A button sitting in a row of labelled fields has no label of its own, so it
   would ride up to the top of the row against the field captions. */
.form-row > button { align-self: flex-end; }
.inv-lines { display: flex; flex-direction: column; gap: 6px; }
.inv-line { display: grid; gap: 6px; align-items: center;
  grid-template-columns: minmax(140px, 3fr) 70px 60px 110px 90px 80px 32px; }
.inv-line input, .inv-line select, .form-row input, .form-row select {
  background: var(--card-2); border: 1px solid var(--rule); color: var(--body);
  border-radius: 6px; padding: 7px 9px; font: inherit; font-size: 13px; min-width: 0; }
.inv-totals { margin-top: 14px; display: flex; flex-direction: column; gap: 4px;
  align-items: flex-end; font-size: 13px; color: var(--muted); }
.inv-total-row.is-total { color: var(--white); font-weight: 600; font-size: 15px; }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; }
td.late { color: var(--warn); }

/* ── invoices: one list at a time, plus search ─────────────── */
.head-tools { display: flex; gap: 8px; align-items: center; }
.head-tools input[type="search"] {
  background: var(--card-2); border: 1px solid var(--rule); color: var(--body);
  border-radius: 6px; padding: 7px 10px; font: inherit; font-size: 13px; min-width: 290px; }
.head-tools input[type="search"]::placeholder { color: var(--muted); }
table.rows-clickable tbody tr { cursor: pointer; }
table.rows-clickable tbody tr:hover { background: var(--card-2); }
.fact-grid { display: flex; flex-wrap: wrap; gap: 10px 28px; margin: 4px 0 18px; }
.fact { display: flex; flex-direction: column; gap: 2px; }
.fact-k { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.fact-v { font-size: 14px; color: var(--body); }
#inv-customer-form { padding: 12px 14px; border: 1px solid var(--rule);
  border-radius: var(--r); background: var(--card-2); align-items: flex-end; }
#inv-customer-form button { align-self: flex-end; }
.form-row button { align-self: flex-end; }

/* The company's own details, and what is still missing from them.
   `.note-inline` breaks long words because it is normally showing a token or a
   digest; here it is showing sentences, so that is put back. */
#co-problems { border-left-color: var(--stop); word-break: normal; }
#co-problems ul { margin: 8px 0 10px 18px; }
#co-problems li { margin: 3px 0; }
#co-problems button { margin-top: 2px; }
#co-panel .form-row { margin-bottom: 10px; }
#co-panel label { min-width: 160px; }

/* ── what needs attention ────────────────────────────────────────────────────
   Between the figures and the tabs, and absent when there is nothing. A bar
   that is permanently green is a strip of screen the eye learns to skip, which
   is exactly the wrong habit to have trained on the day it turns red. */
.attention { padding: 0 22px 4px; display: grid; gap: 8px; }
.att-row {
  padding: 11px 14px; border-radius: var(--r);
  background: var(--card-2); border-left: 3px solid var(--warn);
  font-size: 13px; line-height: 1.55;
}
.att-row.is-stop { border-left-color: var(--stop); }
.att-row.is-unknown { border-left-color: var(--rule); color: var(--muted); }
.att-do { color: var(--dim); font-size: 12.5px; margin-top: 3px; }
@media (max-width: 620px) { .attention { padding: 0 14px 4px; } }

/* ── boards ──────────────────────────────────────────────────────────────────
   A pipeline, a task list and a support queue are one screen because they are
   one mechanism. Columns scroll sideways rather than shrinking: a stage with
   eleven deals in it and no room to show them is a stage nobody looks at. */
.board-pick { display: flex; gap: 10px; align-items: center; }
.board-select, #board-select {
  background: var(--card-2); color: var(--white); border: 1px solid var(--rule);
  border-radius: var(--r); padding: 7px 10px; font: inherit; font-size: 13px;
  min-width: 220px;
}
.board-modes { display: flex; gap: 6px; }

.forecast {
  display: flex; gap: 26px; flex-wrap: wrap; align-items: baseline;
  padding: 12px 14px; margin-bottom: 12px;
  background: var(--card-2); border-radius: var(--r); border-left: 3px solid var(--accent);
  font-size: 13px;
}
.forecast b { color: var(--white); font-weight: 600; }
.forecast .fc-note { color: var(--muted); font-size: 12.5px; }

/* Columns are all the same height, and an empty one is as tall as a full one.
   With `align-items: flex-start` an empty column is a sixty-pixel strip under
   its own heading, which is a target somebody has to aim at — and the empty
   column is precisely the one every card is being dragged into. */
.kanban {
  display: flex; gap: 12px; align-items: stretch;
  overflow-x: auto; padding-bottom: 10px; min-height: 320px;
}
.kcol {
  flex: 0 0 268px; background: var(--card-2); border-radius: var(--r);
  border: 1px solid var(--rule); display: flex; flex-direction: column;
  max-height: 66vh;
}
.kcol-head {
  padding: 10px 12px; border-bottom: 1px solid var(--rule);
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
}
.kcol-name { font-weight: 600; font-size: 13px; color: var(--white); }
.kcol-meta { font-size: 11.5px; color: var(--muted); font-family: var(--mono); }
.kcol-meta.over { color: var(--warn); }
.kcol-body {
  padding: 8px; overflow-y: auto; display: grid; gap: 8px;
  /* `align-content: start` so two cards sit at the top of a tall column rather
     than spreading down it; `flex: 1` so the rest of that column is still the
     column, and a drop anywhere in it lands. */
  align-content: start; flex: 1 1 auto; min-height: 60px;
}
.kcol.is-terminal { border-color: color-mix(in srgb, var(--accent) 40%, var(--rule)); }
/* Where the card would land. Shown rather than guessed at: a drop with no
   indication of where it is going is a drop people undo. */
.kcol.is-over { border-color: var(--accent); }

.kcard {
  background: var(--card); border: 1px solid var(--rule); border-radius: var(--r);
  padding: 10px 11px; cursor: grab; font-size: 13px; line-height: 1.5;
}
.kcard:active { cursor: grabbing; }
.kcard.is-dragging { opacity: .4; }
.kcard-title { color: var(--white); font-weight: 500; }
.kcard-sub { color: var(--dim); font-size: 12px; margin-top: 3px; }
.kcard-foot {
  display: flex; justify-content: space-between; gap: 8px; margin-top: 7px;
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
}
.kcard-value { color: var(--white); }
.kcard.is-lead .kcard-sub::after { content: " · lead"; color: var(--muted); }
.kcard.is-late .kcard-foot { color: var(--stop); }
.kcard-flag { color: var(--accent); }

@media (max-width: 620px) {
  .kcol { flex-basis: 82vw; }
}

/* ── what the advisory skills have written ─────────────── */
.note-row {
  display: block; width: 100%; text-align: left; background: var(--card-2);
  border: 1px solid var(--rule); border-radius: var(--r);
  padding: 12px 14px; margin-bottom: 8px; color: var(--body);
}
.note-row:hover { border-color: var(--accent); }
.note-headline { color: var(--white); font-weight: 500; }
.note-meta {
  display: flex; flex-wrap: wrap; gap: 12px; margin-top: 5px;
  color: var(--muted); font-size: 12px;
}
.note-body { max-width: 68ch; }
.note-body h3, .note-body h4 { margin: 18px 0 6px; font-size: 13px; }
.note-body p { margin: 0 0 12px; line-height: 1.65; }
.note-body b { color: var(--white); font-weight: 600; }
/* The gaps get their own block rather than a paragraph. "Your chart of accounts
   does not separate direct costs from overheads" is something to act on, and
   inside four paragraphs it is something nobody acts on. */
.note-gaps {
  margin: 18px 0; padding: 12px 14px; border-radius: var(--r);
  background: var(--card-2); border-left: 3px solid var(--warn);
}
.note-gaps-head { color: var(--warn); font-size: 12.5px; font-weight: 600; margin-bottom: 6px; }
.note-gaps ul { margin: 0; padding-left: 18px; color: var(--dim); font-size: 13px; }
.note-evidence { margin-top: 14px; }
.note-evidence summary { color: var(--muted); font-size: 12.5px; cursor: pointer; }
.note-evidence summary:hover { color: var(--body); }
.note-evidence pre {
  max-height: 340px; overflow: auto; background: var(--card-2);
  border: 1px solid var(--rule-soft); border-radius: var(--r);
  padding: 12px; font-size: 11.5px; color: var(--dim); margin-top: 10px;
}

/* ── the books, kept by hand ─────────────────────────────────────────────────
 *
 * A retired account is still in the chart and still on the trial balance; what
 * changed is that nothing new can be posted to it. So it is dimmed rather than
 * removed — a row that disappears reads as an account that was deleted, which
 * is the one thing this product will not do.
 */
tr.is-off td { color: var(--muted); }
tr.is-off td.code { opacity: 0.7; }

/* The line being typed. Same grid as an invoice line, three columns narrower:
   an account, a debit, a credit, and the button that drops it. */
#e-lines .inv-line {
  grid-template-columns: minmax(200px, 3fr) 120px 120px 32px;
}

/* ── Chat ──────────────────────────────────────────────────────
   Two columns on a laptop, one on a phone. The rail scrolls
   independently of the conversation, because the two move at
   completely different speeds: a channel list changes weekly and a
   conversation changes while you are reading it. */
.chat {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

.chat-rail {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 12px;
  max-height: calc(100vh - 160px);
  overflow-y: auto;
}

.chat-rail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 8px 0 6px;
}
.chat-rail-head h2 {
  font-size: 12px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.chat-list { display: flex; flex-direction: column; gap: 2px; }

.chat-row {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-radius: 6px;
  padding: 6px 8px;
  font: inherit;
  color: var(--body);
  cursor: pointer;
}
.chat-row:hover { background: var(--card-2); }
.chat-row.is-active { background: var(--accent-dim); color: var(--white); }
.chat-row .pill { margin-left: auto; }
.chat-row .pill.is-you { background: var(--accent); color: var(--on-accent); }

.chat-main {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  display: flex;
  flex-direction: column;
  min-height: 60vh;
  max-height: calc(100vh - 160px);
}

.chat-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--rule-soft);
}
.chat-head h2 { margin: 0; font-size: 16px; }
.chat-sub { margin: 2px 0 0; color: var(--muted); font-size: 13px; }
.chat-live { color: var(--muted); font-size: 12px; white-space: nowrap; }

.chat-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* A short conversation sits above the composer rather than at the top of an
   empty pane, which is what every chat client does and what makes a quiet
   channel read as quiet rather than as broken. `margin-top: auto` on the first
   child rather than `justify-content: flex-end` on the container: the latter
   clips the top of the content once it overflows, in every browser. */
.chat-scroll > :first-child { margin-top: auto; }

.chat-day {
  align-self: center;
  margin: 6px 0;
  font-size: 12px;
  color: var(--muted);
}

.chat-msg { max-width: 68ch; }
.chat-msg.is-agent {
  border-left: 2px solid var(--accent);
  padding-left: 10px;
}

.chat-msg-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 2px;
  flex-wrap: wrap;
}
.chat-msg-who { font-weight: 600; color: var(--white); }
.chat-msg-when { color: var(--muted); font-size: 12px; }

/* What the agent is, next to its name, on every surface that draws a
   message. It is built on the server for exactly that reason. */
.chat-tag {
  font-size: 11px;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 0 6px;
}

.chat-body { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.chat-at { color: var(--accent); }
.chat-removed { margin: 0; color: var(--muted); font-style: italic; }

.chat-chip {
  display: inline-block;
  margin: 6px 6px 0 0;
  padding: 2px 8px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--card-2);
  color: var(--dim);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

/* Shown on hover rather than always: three buttons under every message is a
   conversation that reads as a control panel. */
.chat-actions { margin: 2px 0 0; display: flex; gap: 10px; opacity: 0; }
.chat-msg:hover .chat-actions,
.chat-msg:focus-within .chat-actions { opacity: 1; }
.chat-actions .btn-ghost { font-size: 12px; padding: 0; }

.chat-task { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.chat-task input { flex: 1; min-width: 200px; }

.chat-composer {
  border-top: 1px solid var(--rule-soft);
  padding: 10px 16px 12px;
  position: relative;
}
.chat-composer textarea { width: 100%; resize: vertical; }
.chat-composer-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 6px;
}

.chat-suggest {
  position: absolute;
  bottom: 100%;
  left: 16px;
  right: 16px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  box-shadow: var(--shadow);
  overflow: hidden;
  z-index: 5;
}
.chat-suggestion {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  border: 0;
  background: none;
  font: inherit;
  color: var(--body);
  text-align: left;
  padding: 6px 10px;
  cursor: pointer;
}
.chat-suggestion:hover { background: var(--card-2); }

@media (max-width: 860px) {
  .chat { grid-template-columns: 1fr; }
  .chat-rail { max-height: 30vh; }
  .chat-main { max-height: none; }
}

/* ── The three pages in front of a session ─────────────────────
   Accepting an invitation, asking for a reset, completing one.
   They reuse the sign-in card rather than having a look of their
   own: the first thing an invited person sees of Boxd should be
   Boxd, not a page that resembles it. */
.signin-forgot { margin: 14px 0 0; font-size: 13px; }
.signin-forgot a { color: var(--dim); text-decoration: none; }
.signin-forgot a:hover { color: var(--accent); }

.entry-note {
  margin: 12px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: var(--muted);
}

.entry-done { margin-top: 4px; }
.entry-done-title {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--white);
}

.entry-cta {
  display: inline-block;
  margin-top: 16px;
  padding: 9px 16px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}
.entry-cta:hover { filter: brightness(1.06); }

.entry-back { margin: 18px 0 0; font-size: 13px; }
.entry-back a { color: var(--dim); text-decoration: none; }
.entry-back a:hover { color: var(--accent); }

/* What an invitation is for, above the form that accepts it. */
.entry-fact {
  margin: 0 0 16px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--dim);
}

/* ── Your account ─────────────────────────────────────────────
   The person rather than the company. */
.chip.ok { color: var(--ok); border-color: var(--ok); }

.tfa-secret {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 10px 0 14px;
}
.tfa-secret code {
  font-size: 15px;
  letter-spacing: 0.12em;
  padding: 8px 12px;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--card-2);
}

/* Shown once and never again, so they are laid out to be read off a screen and
   written down rather than skimmed. */
.tfa-code-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 8px;
  margin-top: 10px;
}
.tfa-code-list code {
  padding: 8px 10px;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--card-2);
  letter-spacing: 0.08em;
}

/* ── finding customers ─────────────────────────────────────────────────────
   Four classes the rest of the back office never needed, and one of them is
   load-bearing rather than decorative: .is-stop is on the two buttons here
   that destroy something — an objection and an erasure — and it is the only
   thing on the row that distinguishes them from "Contacted" before the
   confirm box appears. */

/* A sentence-length field in a row of short ones. Without this, "why this one"
   and the evidence for a lawful basis get the same 180px as a postcode, and
   the one field somebody has to be able to point at later is the hardest to
   read back. */
.form-row label.wide { flex: 1 1 100%; }
.form-row label.wide input { width: 100%; }

/* Table cells here hold two things — a name and a qualifier — so the emphasis
   has to come from a span rather than the cell. */
.strong { color: var(--white); font-weight: 500; }
span.muted { color: var(--muted); }

.row-tools {
  white-space: nowrap;
  text-align: right;
}
.row-tools .btn-ghost {
  font-size: 12px;
  padding: 3px 9px;
  margin-left: 6px;
}
.row-tools .btn-ghost:first-child { margin-left: 0; }

/* Mixed against the token rather than written out as a hex with an alpha on
   the end, because --ok and --stop are both redefined by the dark palette and
   a literal would be the light one in both. */
.btn-ghost.is-go { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 38%, transparent); }
.btn-ghost.is-stop { color: var(--stop); border-color: color-mix(in srgb, var(--stop) 38%, transparent); }
/* The plain hover rule sets colour as well as border, and it would otherwise
   win on colour here — a Delete that turns grey under the pointer. */
.btn-ghost.is-go:hover:not(:disabled) { border-color: var(--ok); color: var(--ok); }
.btn-ghost.is-stop:hover:not(:disabled) { border-color: var(--stop); color: var(--stop); }

.panel-note.is-stop { color: var(--stop); }

/* The waitlist key, and the sentence strangers are being asked to agree to,
   both sit in this block; the key is an address rather than a secret, so it is
   set to be copied rather than hidden. */
#waitlist-form-state { margin-bottom: 14px; }
#waitlist-form-state code { user-select: all; }
#waitlist-form-state .btn-ghost { margin-top: 4px; }

@media (max-width: 720px) {
  .row-tools { white-space: normal; text-align: left; }
  .row-tools .btn-ghost { margin: 4px 6px 0 0; }
}

/* ── moving in: the open sales and purchase ledgers ───────────────────────── */

/* Side by side on a wide screen, because the two are read against each other —
   a company that brought detail for one and a lump sum for the other is the
   common case and the comparison is the point. */
.onb-drops { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
.onb-drops .dropzone { margin: 0; }

.onb-open-row { margin: 14px 0; }
.onb-open-what {
  color: var(--white); font-weight: 500; font-size: 13px; margin-bottom: 2px;
}
.onb-open-figures {
  font-variant-numeric: tabular-nums; font-size: 13.5px; margin-bottom: 8px;
}

/* The way back sits under everything and is not dressed up as an action
   somebody is being invited to take. */
#onb-abandon-wrap { margin-top: 28px; border-top: 1px solid var(--rule-soft); padding-top: 18px; }

@media (max-width: 720px) {
  .onb-drops { grid-template-columns: 1fr; }
}

/* ── leaving ────────────────────────────────────────────────
 *
 * The last screen a company sees. Deliberately plain: this is not a place to
 * be persuaded to stay, and a page that makes leaving feel like an error is
 * the software equivalent of a cancellation phone line.
 */
.end-contents {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 10px; margin: 12px 0 4px;
}
.end-contents .item {
  border: 1px solid var(--rule); border-radius: 8px; padding: 10px 12px;
  background: var(--card-2);
}
.end-contents .n { color: var(--white); font-size: 17px; font-weight: 600; }
.end-contents .what { color: var(--dim); font-size: 12.5px; margin-top: 2px; }

/* One button in this product destroys something, and this is it — so it is the
 * only red one, and it only exists on this panel. A colour used anywhere else
 * would stop meaning anything here. */
.btn-danger {
  background: transparent; color: var(--stop); border: 1px solid var(--stop);
  border-radius: 8px; padding: 9px 18px; font-weight: 600; font-size: 13.5px;
}
.btn-danger:hover:not(:disabled) { background: var(--stop); color: var(--white); }
.btn-danger:disabled { opacity: .45; cursor: not-allowed; }

/* The company has closed. One line, on every screen, for the state that
 * changes what all of them mean. */
.closed-banner {
  margin: 0 0 14px; padding: 10px 14px;
  border: 1px solid var(--rule); border-left: 3px solid var(--stop);
  border-radius: 8px; background: var(--card-2);
  color: var(--body); font-size: 13.5px;
}
.closed-banner b { color: var(--white); font-weight: 600; }

/* ── receipts that are not in the books ─────────────────────
 *
 * A list of photographs and, under each, the entries it might belong to. Plain
 * rows rather than cards: the decision is "is this the payment", and anything
 * decorative around it is one more thing between the person and the answer.
 */
.unplaced-row {
  border: 1px solid var(--rule); border-radius: 8px; padding: 12px 14px;
  margin-bottom: 10px; background: var(--card-2);
}
.unplaced-head { display: flex; flex-wrap: wrap; gap: 10px; align-items: baseline; }
.unplaced-name { color: var(--white); font-weight: 600; font-size: 13.5px; }
.unplaced-what { color: var(--body); font-size: 13px; }
.unplaced-age  { color: var(--dim); font-size: 12.5px; margin-left: auto; }
.unplaced-tools { margin-top: 8px; display: flex; gap: 8px; flex-wrap: wrap; }
.unplaced-hits { margin-top: 8px; display: grid; gap: 6px; }

.hit-row {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  border-top: 1px solid var(--rule-soft); padding-top: 8px;
}
.hit-what { display: grid; gap: 2px; flex: 1 1 320px; min-width: 0; }
.hit-desc { color: var(--white); font-size: 13.5px; }
.hit-meta { color: var(--body); font-size: 12.5px; font-family: var(--mono); }
/* Why it is being offered, which is the half that stops somebody attaching a
   receipt to the wrong coffee. */
.hit-why  { color: var(--dim); font-size: 12.5px; }

/* ── what is behind a figure ────────────────────────────────
 *
 * One panel, opened from any report. A row that can be drilled says so by
 * being clickable rather than by carrying an icon: every row on these tables
 * is drillable except the computed ones, and an arrow on all of them would be
 * decoration on each.
 */
tr.clickable { cursor: pointer; }
tr.clickable:hover td { background: var(--card-2); }
#drill-panel { margin-top: 14px; }
.drill-evidence { margin-top: 12px; }
.drill-doc {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  border-top: 1px solid var(--rule-soft); padding: 8px 0; font-size: 13.5px;
}
.drill-doc .muted { color: var(--dim); font-size: 12.5px; }
.drill-doc button { margin-left: auto; }
