/* LendTrace — the design system from the approved prototype.
 *
 * Tokens and component rules are lifted from `lendtrace-mock/index.html` so
 * the built product and the design the client signed off cannot drift apart by
 * eye. Where this file departs from the prototype it is to add something the
 * prototype had no need of — focus states, reduced motion, print — never to
 * restyle something it already decided.
 *
 * One stylesheet, no build step, no CDN. ADR-0002 says one deployable
 * artefact, and a field agency on a thin connection should pay for one small
 * file rather than a framework.
 */

:root {
  --navy: #10233f;
  --navy-2: #1b3559;
  --navy-3: #26426b;
  --amber: #e8a33d;
  --amber-d: #c9862a;
  --ink: #2c3440;
  --muted: #6b7683;
  --rule: #dde2e8;
  --paper: #f7f8fa;
  --white: #fff;
  --green: #1e8e5a;
  --green-bg: #e7f4ee;
  --red: #c0392b;
  --red-bg: #fbebe9;
  --blue: #2a6fb0;
  --blue-bg: #eaf2f9;
  --amber-bg: #fdf4e6;
  --sh: 0 1px 2px rgba(16, 35, 63, 0.06), 0 4px 12px rgba(16, 35, 63, 0.05);
  --r: 10px;
  /* The one token the prototype implied but never named: the focus ring. */
  --focus: #2a6fb0;
}

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

html,
body {
  height: 100%;
}

body {
  font-family: "Segoe UI", system-ui, -apple-system, Roboto, sans-serif;
  background: var(--paper);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* **Every interactive thing shows where the keyboard is.** The prototype was
 * click-only and never needed this; an operations coordinator working a queue
 * of 400 cases lives on the keyboard, and an invisible focus ring makes the
 * product unusable for them and inaccessible for everyone else. */
:where(a, button, input, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- shell ---------- */
.app {
  display: flex;
  min-height: 100vh;
}

.side {
  width: 232px;
  flex: 0 0 232px;
  background: var(--navy);
  color: #c7d0dc;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}

.brand {
  padding: 20px 18px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.brand h1 {
  font-size: 19px;
  color: #fff;
  letter-spacing: 0.2px;
}

.brand span {
  font-size: 10.5px;
  color: var(--amber);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  display: block;
}

.nav {
  padding: 6px 0 10px;
  overflow-y: auto;
  flex: 1;
}

/* A group's heading folds and unfolds its links, at every width. It used to be
 * a plain label at a desk, with every link shown; the column then came back
 * scrolled to its top after every click and the page just opened sat below the
 * fold (25 September 2026). The group holding this page is marked as well as
 * open, so where a person is reads from the headings alone. */
.nav-grp > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: #8a9bb1;
  padding: 12px 18px 6px;
  cursor: pointer;
  list-style: none;
}

.nav-grp > summary::-webkit-details-marker {
  display: none;
}

/* A chevron that turns, drawn in the stylesheet so it is never read out. */
.nav-grp > summary::after {
  content: "\25B8";
  margin-left: auto;
  font-size: 10px;
  transition: transform 0.15s;
}

.nav-grp[open] > summary::after {
  transform: rotate(90deg);
}

.nav-grp > summary:hover,
.nav-grp[open] > summary {
  color: #c7d0dc;
}

.nav-grp.here > summary {
  color: var(--amber);
}

.nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 18px;
  color: #c7d0dc;
  text-decoration: none;
  font-size: 13.2px;
  border-left: 3px solid transparent;
}

.nav a:hover {
  background: rgba(255, 255, 255, 0.05);
  color: #fff;
}

.nav a[aria-current="page"] {
  background: rgba(232, 163, 61, 0.12);
  border-left-color: var(--amber);
  color: #fff;
  font-weight: 600;
}

.nav .ico {
  width: 16px;
  text-align: center;
  opacity: 0.85;
  font-size: 13px;
}

.side-out {
  padding: 12px 18px 0;
  margin-top: auto;
}

/* The ghost button's navy text is for a white page. On the navy sidebar it was
   navy on navy -- an empty outline where "Sign out" should be, at every width,
   unseen because every test clicks it by selector. The sidebar's own light
   text, and a rule light enough to see. */
.side-out .btn.ghost {
  color: #e3e9f1;
  border-color: rgba(255, 255, 255, 0.35);
}

.side-out .btn.ghost:hover {
  background: var(--navy-2);
}

/* Shrinking the sidebar to its icons, a desk's choice (`nav.js`). The button
 * sits above signing out and reads like a link, because it is navigation
 * furniture rather than an action on the agency's records. */
.side-shrink {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 8px 0 0;
  padding: 8px 18px;
  background: none;
  border: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  color: #8a9bb1;
  font: inherit;
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
}

.side-shrink[hidden] {
  display: none;
}

.side-shrink:hover {
  color: #fff;
}

.side-shrink .ico {
  width: 16px;
  text-align: center;
}

/* Shrunk: a rail of icons, every group's links shown with the groups ruled
 * apart, because a folded group in a rail has no heading to open it by. The
 * words stay in the page for a screen reader and each link's title says them
 * on hover. `width > 900px` because a phone's bar has no rail to shrink to;
 * a shrunk choice made at a desk is simply not applied there. */
@media (width > 900px) {
  :root[data-sidebar="shrunk"] .side {
    width: 60px;
    flex-basis: 60px;
  }

  :root[data-sidebar="shrunk"] .brand span,
  :root[data-sidebar="shrunk"] .side-foot,
  :root[data-sidebar="shrunk"] .nav-grp > summary {
    display: none;
  }

  :root[data-sidebar="shrunk"] .brand {
    padding: 18px 8px 14px;
    text-align: center;
  }

  :root[data-sidebar="shrunk"] .brand h1 {
    font-size: 0;
  }

  :root[data-sidebar="shrunk"] .brand h1::before {
    content: "LT";
    font-size: 17px;
  }

  :root[data-sidebar="shrunk"] .nav-grp + .nav-grp {
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    margin-top: 4px;
    padding-top: 4px;
  }

  :root[data-sidebar="shrunk"] .nav a,
  :root[data-sidebar="shrunk"] .side-shrink {
    justify-content: center;
    padding: 9px 0;
  }

  :root[data-sidebar="shrunk"] .nav .lbl,
  :root[data-sidebar="shrunk"] .side-shrink .lbl,
  :root[data-sidebar="shrunk"] .side-out .lbl {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  :root[data-sidebar="shrunk"] .side-shrink .ico {
    transform: rotate(180deg);
  }

  :root[data-sidebar="shrunk"] .side-out {
    padding: 10px 6px 0;
  }

  :root[data-sidebar="shrunk"] .side-out .btn {
    width: 100%;
    padding-left: 0;
    padding-right: 0;
  }

  :root[data-sidebar="shrunk"] .side-out .btn::before {
    content: "\23FB";
  }
}

/* A closed group's links, shown in the rail. Guarded: a browser that does not
 * know `::details-content` keeps the rail's headings instead of hiding them
 * over links it cannot unfold. */
@supports selector(::details-content) {
  @media (width > 900px) {
    :root[data-sidebar="shrunk"] .nav-grp::details-content {
      display: block;
      content-visibility: visible;
    }
  }
}

@supports not selector(::details-content) {
  @media (width > 900px) {
    :root[data-sidebar="shrunk"] .nav-grp > summary {
      display: flex;
    }
  }
}

/* The phone's Menu button. Hidden at every width unless the script ran
 * (`data-menu` on the root), and shown only on a phone -- see the phone query. */
.side-menu {
  display: none;
}

.side-foot {
  padding: 12px 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 11px;
  color: #6c7e96;
}

.main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.top {
  background: var(--white);
  border-bottom: 1px solid var(--rule);
  padding: 14px 22px;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.top h2 {
  font-size: 19px;
  color: var(--navy);
}

.top .sub {
  font-size: 12.5px;
  color: var(--muted);
}

.top .spacer {
  flex: 1;
}

.wrap {
  padding: 20px 22px 40px;
  max-width: 1500px;
  width: 100%;
}

/* Skip link: the first thing a keyboard reaches, hidden until focused. */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--navy);
  color: #fff;
  padding: 10px 16px;
  z-index: 10;
}

.skip:focus {
  left: 8px;
  top: 8px;
}

/* ---------- atoms ---------- */
.btn {
  background: var(--navy);
  color: #fff;
  border: 0;
  border-radius: 7px;
  padding: 8px 14px;
  font-size: 12.8px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
  display: inline-block;
  /* A button that wraps reads as two words stacked, not as a control. At 390px
   * "Add lender" was breaking across two lines. */
  white-space: nowrap;
}

.btn:hover {
  background: var(--navy-2);
}

.btn.amber {
  background: var(--amber);
  color: var(--navy);
}

.btn.amber:hover {
  background: var(--amber-d);
}

.btn.ghost {
  background: transparent;
  color: var(--navy);
  border: 1px solid var(--rule);
}

.btn.ghost:hover {
  background: var(--paper);
}

.btn.sm {
  padding: 5px 10px;
  font-size: 11.5px;
}

.btn[aria-disabled="true"] {
  opacity: 0.45;
  pointer-events: none;
}

.card {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  box-shadow: var(--sh);
}

/* A header wraps rather than pushing the page sideways. The case file's own
 * header carries a heading, a stage pill, sometimes a hold pill and up to two
 * links, and adding the read-only answers page to it overflowed a 390px screen
 * by 43px — caught by the browser tier, which is the only one that measures a
 * rendered width. Wrapping engages exactly when the row would otherwise
 * overflow, so it changes nothing on any header that already fits. */
.card-h {
  padding: 13px 16px;
  border-bottom: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.card-h h3 {
  font-size: 14.5px;
  color: var(--navy);
}

.card-h .spacer {
  flex: 1;
}

.card-b {
  padding: 16px;
}

/* A form or a paragraph put straight into a card, with no `.card-b` or
 * `.form-grid` around it, had no room at all: its label, chooser and button
 * sat against the card's border at every width. Twenty-eight forms on the case
 * file alone are written that way -- allocate, next steps, people -- and the
 * setup screens' introductions too. Found walking a fresh agency on a phone
 * (25 September 2026). One rule here rather than a wrapper in each template,
 * so a form added the same way later is not the one that forgets.
 * `.refused` keeps its own spacing: it is a banner, not a paragraph of prose.
 * **Not a form that already has its room**: eight hold a padded `.form-grid`
 * or `.card-b`, or a `.form-foot` bar meant to run the card's full width, and
 * the first version of this rule padded those twice. */
.card > form:not(:has(.form-grid, .card-b, .form-foot)),
.card > p:not(.refused) {
  padding: 12px 16px;
}

.card > form:not(:has(.form-grid, .card-b, .form-foot)) > * + * {
  margin-top: 10px;
}

/* A new agency's first steps (`api/agency_setup.py`): a real sequence, so a
 * numbered list, each step on its own line with its note beneath it. */
.setup-steps {
  margin: 12px 0 0;
  padding-left: 20px;
  display: grid;
  gap: 10px;
}

.setup-steps .tiny {
  display: block;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2.5px 9px;
  border-radius: 99px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.p-green {
  background: var(--green-bg);
  color: var(--green);
}

.p-red {
  background: var(--red-bg);
  color: var(--red);
}

.p-amber {
  background: var(--amber-bg);
  color: #8a6115;
}

.p-blue {
  background: var(--blue-bg);
  color: var(--blue);
}

.p-grey {
  background: #eef1f5;
  color: var(--muted);
}

.dot {
  width: 6px;
  height: 6px;
  border-radius: 99px;
  background: currentColor;
  flex: 0 0 6px;
}

/* ---------- table ---------- */
.scroller {
  overflow-x: auto;
}

/* Here rather than a `style=` attribute on the element: the content security
 * policy carries no `unsafe-inline`, so an inline style would simply not
 * apply — and silently, which is the worst way for a rule to fail. */
caption {
  padding: 8px 12px;
  text-align: left;
}

table {
  width: 100%;
  border-collapse: collapse;
}

th {
  text-align: left;
  font-size: 10.5px;
  letter-spacing: 0.7px;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 700;
  padding: 9px 12px;
  border-bottom: 1px solid var(--rule);
  background: #fbfcfd;
}

td {
  padding: 10px 12px;
  border-bottom: 1px solid #edf0f4;
  font-size: 13px;
  vertical-align: middle;
}

tr:last-child td {
  border-bottom: 0;
}

/* --- A table somebody types into ------------------------------------------
 *
 * A repeating question on the capture form is a table of boxes. It takes the
 * same `.scroller` and `data-label` treatment every other table here does, so
 * it stacks into a card per row at a handset's width -- which is the whole
 * reason it is a table element and not a grid of divs.
 */

/* The group's own label, carried by the table's caption rather than by a
 * `<label for>`: the name belongs to the table, and the first box is not it.
 * Matches `.field label` exactly, because it is one. */
caption .cap-name {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--navy);
  margin-bottom: 5px;
}

/* A cell is a flex item once a row becomes a card, and `min-width: auto` on an
 * input is its intrinsic width -- around twenty characters, which will not
 * shrink beside a 96px label at 390px and takes the page sideways instead.
 * Found at the width where this class of defect is only ever found. */
td input[type="text"],
td select {
  min-width: 0;
}

/* **One cell, never the whole table.** A refusal that colours every row
 * reports that everything typed was wrong, which is the defect
 * `/settings/configuration` already paid for. Mirrors `.field.bad` because it
 * means the same thing in the same form. */
td.bad input[type="text"],
td.bad select {
  border-color: var(--red);
  background: var(--red-bg);
}

tbody tr:hover {
  background: #fafbfd;
}

/* The whole row is the target, but the link is what the keyboard and a screen
 * reader follow — a `tr` with a click handler is reachable by neither. */
td .row-link {
  color: var(--navy);
  font-weight: 600;
  text-decoration: none;
}

td .row-link:hover {
  text-decoration: underline;
}

.mono {
  font-family: "Cascadia Mono", Consolas, monospace;
  font-size: 12px;
}

.muted {
  color: var(--muted);
}

.tiny {
  font-size: 11.5px;
}

.num {
  font-variant-numeric: tabular-nums;
}

.right {
  text-align: right;
}

/* ---------- tabs ---------- */
.tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.tabs a {
  background: none;
  border: 0;
  padding: 9px 14px;
  font-size: 13px;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  font-family: inherit;
  font-weight: 600;
}

.tabs a[aria-current="page"] {
  color: var(--navy);
  border-bottom-color: var(--amber);
}

/* ---------- callouts ---------- */
.note {
  background: var(--blue-bg);
  border-left: 3px solid var(--blue);
  padding: 10px 13px;
  border-radius: 0 6px 6px 0;
  font-size: 12.5px;
  color: #1e4e7c;
}

.empty {
  padding: 48px 24px;
  text-align: center;
  color: var(--muted);
}

.empty strong {
  display: block;
  color: var(--navy);
  font-size: 15px;
  margin-bottom: 4px;
}

/* ---------- pagination ---------- */
.pager {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--rule);
  font-size: 12.5px;
  color: var(--muted);
}

.pager .spacer {
  flex: 1;
}

/* ---------- responsive ---------- */
/* **A table becomes a list of cards on a phone, never a sideways scroll.**
 * Five columns cannot fit 390px, and horizontally scrolling a table hides the
 * columns that matter behind a gesture nobody discovers. The prototype's own
 * narrow view stacks cards for the same reason. Each cell carries its label
 * through `data-label`, so a card reads "Applicant — Ramesh Gowda" rather than
 * leaving a bare value whose meaning was in a header now hidden.
 *
 * The `table` element stays: it is still tabular data, screen readers still
 * announce it as such, and only the presentation changes. */
@media (max-width: 760px) {
  .scroller {
    overflow-x: visible;
  }

  table,
  tbody,
  tr,
  td,
  caption {
    /* `caption` is in this list deliberately. Left as `table-caption` inside a
     * table whose own display is `block`, it keeps table-layout behaviour and
     * drags the whole card wider than the viewport — the card's right edge then
     * sits off-screen, taking the pager with it. */
    display: block;
    width: 100%;
  }

  td {
    /* A cell is a block at this width and `.scroller` is `visible`, so nothing
     * absorbs a long unbreakable token any more — it pushes the whole page
     * sideways instead. Field keys are exactly that shape
     * (`core.applicant_work_experience_years`), and the template editor's
     * wording table is a column of them. Found by the browser tier at 390px,
     * which is where this class of defect is only ever found. */
    overflow-wrap: anywhere;
  }

  thead {
    /* Hidden from sight, kept for assistive technology. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  tbody tr {
    border: 1px solid var(--rule);
    border-radius: 8px;
    margin: 10px 12px;
    padding: 4px 0;
    background: var(--white);
    /* `auto`, not the 100% the rule above gives every stacked element: a
     * block's width *and* 12px of margin each side is 24px more than its
     * container, so every row card on every stacked table stood past the
     * right edge of its card. Found on a phone on the questions screen
     * (25 September 2026); no page scrolled sideways, because the card's own
     * margin absorbed it, so the page-width checks could not see it. */
    width: auto;
  }

  tbody tr:hover {
    background: var(--white);
  }

  td {
    display: flex;
    gap: 12px;
    align-items: baseline;
    border-bottom: 0;
    padding: 6px 12px;
  }

  td::before {
    content: attr(data-label);
    flex: 0 0 96px;
    font-size: 10.5px;
    letter-spacing: 0.7px;
    text-transform: uppercase;
    color: var(--muted);
    font-weight: 700;
  }

  /* The case reference is the card's title, so it loses its label and grows. */
  td[data-label="Case"] {
    padding-top: 10px;
  }

  td[data-label="Case"]::before {
    content: none;
  }

  td[data-label="Case"] .row-link {
    font-size: 15px;
  }

  caption {
    padding: 10px 12px !important;
  }

  .pager {
    flex-wrap: wrap;
  }
}

@media (max-width: 900px) {
  .app {
    flex-direction: column;
  }

  /* The name on one row, the sections beneath it, signing out last -- in the
   * order they are in the page, so the keyboard meets them in the order the
   * eye does. The name used to share a row with the links, which left them a
   * column 145px wide: twenty-two links stood one to a line, clipped, and the
   * page's own header began below a 390 by 844 screen. */
  .side {
    width: 100%;
    flex: none;
    height: auto;
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
  }

  .brand {
    flex: 1 1 100%;
    padding: 12px 14px 10px;
    display: flex;
    align-items: center;
    gap: 12px;
  }

  /* **One Menu button, naming the page** (register P1). Seven folded headings
   * still took the first half of a phone's screen before the page began; with
   * the script present the sections sit behind this button, closed on every
   * page, and the button says where the person is. Without the script there
   * is no button and the folded headings are shown, which still works. */
  :root[data-menu] .side-menu {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-end;
    margin-left: auto;
    min-height: 44px;
    justify-content: center;
    padding: 6px 14px;
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 8px;
    color: #fff;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
  }

  .menu-here {
    font-size: 11px;
    font-weight: 400;
    color: var(--amber);
    max-width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  :root[data-menu="closed"] .side .nav {
    display: none;
  }

  /* **Folded to its headings, so it is a few rows however many links a role
   * earns.** The group holding this page opens with it; any other is a tap on
   * its heading, which folds the open one away (`name` in `base.html`). The
   * links inside an open group wrap rather than scroll: a bar that scrolls
   * sideways has no affordance saying so, and the links past the fold are
   * simply not found -- which is what the last version of this rule learned
   * when a fourth link went off the edge. */
  .nav {
    flex: 1 1 100%;
    padding: 0;
    overflow: visible;
  }

  .nav-grp {
    border-top: 1px solid rgba(255, 255, 255, 0.08);
  }

  /* A heading a thumb can hit: forty-odd pixels high and the whole width. */
  .nav-grp > summary {
    padding: 12px 14px;
    font-size: 11px;
    color: #c7d0dc;
  }

  .nav-grp[open] > summary {
    color: #fff;
  }

  .nav-links {
    display: flex;
    flex-wrap: wrap;
    padding: 0 0 6px;
  }

  .side-foot,
  .side-shrink {
    display: none;
  }

  /* The byline goes at this width; signing out does not. A field executive
     works from a phone, and an account they cannot put down on the device they
     carry is the one that matters most. Kept out of `.nav`, so it is never
     folded away inside a group. */
  .side-out {
    padding: 8px 12px;
    margin: 0;
  }

  .nav a {
    border-left: 0;
    border-bottom: 3px solid transparent;
    white-space: nowrap;
  }

  .nav a[aria-current="page"] {
    border-left: 0;
    border-bottom-color: var(--amber);
  }

  .wrap {
    padding: 16px 14px 32px;
  }
}

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

/* ---------- sign-in ----------
 * The prototype's centred card on the navy field. Its two-column layout listed
 * demonstration accounts to click; there are none here, so the card stands
 * alone rather than beside an empty space where a list used to be.
 */
.signin-page {
  background: var(--navy);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.signin {
  width: 100%;
  max-width: 380px;
}

.signin-card {
  background: var(--white);
  border-radius: var(--r);
  padding: 32px 30px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.28);
}

.signin-eyebrow {
  display: block;
  font-size: 10.5px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--amber-d);
  font-weight: 700;
}

.signin-card h1 {
  font-size: 27px;
  color: var(--navy);
  margin-top: 6px;
}

.signin-sub {
  color: var(--muted);
  font-size: 13.5px;
  margin-top: 2px;
}

.signin-by {
  border-left: 3px solid var(--amber);
  padding: 2px 0 2px 11px;
  margin: 22px 0;
}

.signin-by span {
  display: block;
  font-size: 9.5px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--muted);
}

.signin-by strong {
  color: var(--navy);
  font-size: 14.5px;
}

.signin-go {
  width: 100%;
  padding: 12px;
  font-size: 14px;
}

.signin-msg:empty {
  display: none;
}

.signin-msg {
  margin-top: 14px;
  background: var(--red-bg);
  border-left: 3px solid var(--red);
  padding: 9px 12px;
  border-radius: 0 6px 6px 0;
  font-size: 12.5px;
  color: #8e2c21;
}

.signin-help {
  margin-top: 18px;
  font-size: 11.5px;
  color: var(--muted);
  line-height: 1.45;
}

/* The backup-code form, folded away beneath the passkey button: it is the way
 * in for the morning something has gone wrong, not the ordinary one. */
.signin-alt {
  margin-top: 18px;
  border-top: 1px solid var(--rule);
  padding-top: 14px;
}

.signin-alt summary {
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--navy);
}

.signin-alt .field,
.signin-alt .signin-go,
.signin-alt .refused {
  margin-top: 12px;
}

/* --- Forms -----------------------------------------------------------------
 *
 * The prototype had no form, so these are new rather than lifted — built from
 * its own tokens so they read as the same product.
 *
 * **The label is always visible.** A placeholder used as a label disappears the
 * moment somebody types, which leaves a half-filled form nobody can check, and
 * it is invisible to a screen reader. Every field here has a real `<label>`.
 */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 16px;
  padding: 16px;
  /* `docs/UI-STANDARD.md` §1: a form is at most 720px wide and left-aligned,
   * whatever the screen. Before this a name box on a 1920px laptop was about
   * 1,500px wide (Devarajan, 25 September 2026). */
  max-width: 720px;
}

/* A card that *is* a form is as wide as its form, so a 720px form does not sit
 * in a card spanning a 1920px screen with the rest of it empty. Cards holding
 * lists and tables stay the width of the page. */
form.card {
  max-width: 752px;
}

/* What a field holds decides its width (`_forms.html`'s `size`). `md` fills
 * one column, which is already a sensible width inside a 720px form. */
.field.size-xs input,
.field.size-xs select {
  max-width: 8rem;
}

.field.size-sm input,
.field.size-sm select {
  max-width: 12rem;
}

.field.size-full {
  grid-column: 1 / -1;
}

/* A label and its ⓘ on one line. */
.field-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 5px;
}

.field .field-head label {
  margin-bottom: 0;
}

.field .optional {
  font-weight: 400;
  color: var(--muted);
}

/* The ⓘ: a small round button that opens a short panel on a tap or a click,
 * and from the keyboard -- a `details`, so it needs no script. */
.info {
  position: relative;
}

.info > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--muted);
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  font-style: italic;
  line-height: 1;
}

.info > summary::-webkit-details-marker {
  display: none;
}

.info[open] > summary,
.info > summary:hover {
  border-color: var(--navy);
  color: var(--navy);
}

.info > p {
  position: absolute;
  z-index: 5;
  top: calc(100% + 6px);
  left: -8px;
  width: min(22rem, 80vw);
  margin: 0;
  padding: 10px 12px;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: 7px;
  box-shadow: var(--sh);
  font-size: 12px;
  font-weight: 400;
  color: var(--ink);
  line-height: 1.45;
}

.form-note {
  font-size: 12px;
  color: var(--muted);
}

/* A field that reads as one thought spans the row rather than being squeezed
 * beside an unrelated one. */
.field.wide {
  grid-column: 1 / -1;
}

.field label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--navy);
  margin-bottom: 5px;
}

.field .hint {
  display: block;
  font-size: 11.5px;
  color: var(--muted);
  font-weight: 400;
  margin-top: 3px;
  /* A hint can carry an unbroken token -- a lender's portal address on the
   * delivery checklist -- and at 390px one would push the page sideways. */
  overflow-wrap: anywhere;
}

/* `email` and `date` are here beside `text` rather than left out: the company
 * profile takes an address and the configuration registry takes the day a
 * value starts, and a browser gives each of those a keyboard and a picker that
 * a text box does not. An input the stylesheet does not name renders as the
 * browser's own control in the middle of a styled form — which is exactly the
 * kind of thing only the browser tier sees. `invite.html` and
 * `user_roles.html` were already in that state and are fixed by this. */
.field input[type="text"],
.field input[type="email"],
.field input[type="date"],
.field select {
  width: 100%;
  font-family: inherit;
  font-size: 13.5px;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: 7px;
  padding: 8px 10px;
}

.field input[type="text"]:hover,
.field input[type="email"]:hover,
.field input[type="date"]:hover,
.field select:hover {
  border-color: var(--navy-3);
}

/* The country code sits in its own box and never moves, so the ten digits
 * beside it are the only thing anybody types (decided 2026-08-17). */
.phone {
  display: flex;
  gap: 8px;
}

.phone .code {
  flex: 0 0 62px;
  text-align: center;
  background: var(--paper);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* An applicant's country code is shown and never typed, so it wears the muted
 * read-only box above. The agency's own is a real column and is editable, and
 * a box somebody must type into must not look like one they cannot. */
.phone .code:not([readonly]) {
  background: var(--white);
  color: var(--ink);
}

/* `:not(.code)`, because `input[type="text"]` outranks `.code` alone: without
 * it the country code grew to half the row on the company profile, unnoticed
 * until the invitation form put one beside the UI standard (25 Sep 2026). */
.phone input[type="text"]:not(.code) {
  flex: 1 1 auto;
}

/* The queue's filters. A row where there is room and stacked where there is
 * not: the controls are a select, a checkbox and a button, and somebody on a
 * handset should not have to scroll sideways to reach the last of them. */
.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
  margin-bottom: 14px;
}

.filters .field {
  margin: 0;
}

/* Label beside the control rather than above it, because these are one line of
 * a sentence — "stage: validation, only mine" — not a form to fill in. */
.filters .field.inline {
  display: flex;
  align-items: center;
  gap: 8px;
}

.filters .field.inline label {
  margin: 0;
  white-space: nowrap;
}

/* A checkbox is a decision, so it gets the same weight as a labelled field
 * rather than being tucked under one. */
.check {
  display: flex;
  align-items: flex-start;
  gap: 9px;
}

.check input {
  margin-top: 2px;
  width: 15px;
  height: 15px;
  accent-color: var(--navy);
  flex: 0 0 auto;
}

.check label {
  margin: 0;
  font-weight: 600;
}

.form-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 16px;
  border-top: 1px solid var(--rule);
  background: var(--paper);
  border-radius: 0 0 var(--r) var(--r);
}

/* A refusal names the field and says what is wrong with it. `role="alert"`
 * so a screen reader announces it instead of leaving somebody re-reading a
 * form that looks unchanged. */
/* Wraps anywhere because what it prints is people's words: a hold's reason is
   free text, and a pasted reference number with no space in it pushed a held
   case's file 175px past a phone's edge. Unreachable until the workflow made
   holds real; found by the browser tier the day it did. */
.refused {
  margin: 16px 16px 0;
  padding: 10px 12px;
  border: 1px solid var(--red);
  background: var(--red-bg);
  color: var(--red);
  border-radius: 7px;
  font-size: 12.8px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

/* `textarea` too: a reason, a note and a hold's explanation are all refused
 * beside a textarea, and until 24 September the box the refusal was about was
 * the one box on the page that did not turn red. */
.field.bad input[type="text"],
.field.bad input[type="email"],
.field.bad input[type="date"],
.field.bad select,
.field.bad textarea {
  border-color: var(--red);
  background: var(--red-bg);
}

/* A set of choices a person may tick several of -- the roles a new joiner is
 * given. A fieldset, so the legend names the set for a screen reader the way a
 * label names a field; the choices flow into as many columns as fit. */
.choice-set {
  grid-column: 1 / -1;
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

.choice-set legend {
  font-size: 12px;
  font-weight: 600;
  color: var(--navy);
  margin-bottom: 6px;
  padding: 0;
}

.choice-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 6px 16px;
}

.choice-list label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}

.choice-list input {
  width: 15px;
  height: 15px;
  accent-color: var(--navy);
  flex: 0 0 auto;
}

.choice-set.bad .choice-list {
  outline: 1px solid var(--red);
  outline-offset: 4px;
  border-radius: 4px;
}

.choice-set .hint {
  display: block;
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 6px;
}

/* My profile: a person's own record, read-only. As wide as a form, since it
 * is a list of facts rather than a table. */
.card.profile {
  max-width: 752px;
}

.card-note {
  padding: 12px 16px;
  margin: 0;
  font-size: 12.5px;
  color: var(--muted);
}

.card-note a {
  color: var(--navy);
  font-weight: 600;
}

.profile-role {
  padding: 12px 16px;
  border-top: 1px solid var(--rule);
}

.card-h + .profile-role {
  border-top: 0;
}

.profile-role h4 {
  margin: 0 0 6px;
  font-size: 13.5px;
  color: var(--navy);
}

.allows {
  margin: 0;
  padding-left: 18px;
  font-size: 13px;
  line-height: 1.6;
}

/* --- One case --------------------------------------------------------------
 *
 * A definition list, because that is what a case file is: a label and its
 * value. A table would imply rows that can be compared across.
 */
.facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px 16px;
  padding: 16px;
  margin: 0;
}

.facts > div {
  min-width: 0;
}

.facts dt {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 3px;
}

.facts dd {
  margin: 0;
  font-size: 14px;
  color: var(--ink);
  overflow-wrap: anywhere;
}

@media (max-width: 720px) {
  .form-grid,
  .facts {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Cards that follow one another are spaced by a rule, never by an inline
 * `style` attribute: the policy forbids inline styles outright (`style-src
 * 'self'`, no `unsafe-inline`), so one would be silently dropped and the page
 * would render wrong in exactly the way the unstyled sign-in page did. */
.wrap .card + .card {
  margin-top: 16px;
}

/* --- Relationships ---------------------------------------------------------
 *
 * Blocks rather than table rows: each carries actions as well as facts, and an
 * agency has five of these rather than five hundred.
 */
.rel-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rel + .rel {
  border-top: 1px solid var(--rule);
}

.rel-h {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  padding: 13px 16px 0;
}

/* `.spacer` is only `flex: 1` where a rule says so — it is a hook, not a
 * component — so without this the actions sit against the lender's name
 * instead of at the far end of the row. Suspend and Close directly under the
 * eye's path while scanning a list is exactly where they should not be. */
.rel-h .spacer {
  flex: 1;
}

.rel-h form {
  display: inline;
}

/* One sentence between a page's chooser and its first card. */
.page-note {
  margin: 0 0 16px;
}

/* A line beneath a row's heading: what a setting does, and where its value
 * comes from. */
.rel-note {
  margin: 4px 16px 0;
  color: var(--muted);
}

.facts.tight {
  padding: 10px 16px 14px;
  gap: 10px 16px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* A section of the questions screen: folded until somebody opens it, because
 * two hundred and eighty-seven questions open at once is a page nobody reads. */
.library-section {
  border-top: 1px solid var(--rule);
}

.library-section > summary {
  cursor: pointer;
  padding: 12px 16px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  color: var(--navy);
}

.library-section > summary:hover {
  color: var(--amber-d);
}

.rel-edit {
  border-top: 1px dashed var(--rule);
  margin: 0 16px 14px;
}

.rel-edit summary {
  cursor: pointer;
  padding: 9px 0 0;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--navy);
}

.rel-edit summary:hover {
  color: var(--amber-d);
}

.rel-edit .form-grid,
.rel-edit .form-foot {
  padding-left: 0;
  padding-right: 0;
}

.rel-edit .form-foot {
  background: transparent;
  border-top: 0;
}

/* A refusal that belongs to the page rather than to the form beneath it. */
.refused.standalone {
  margin: 0 0 16px;
}

/* A one-time link, shown to be copied. `anywhere` rather than `break-all`
   because the string is a URL with no spaces in it: without a break rule it
   sets as one unbreakable word, pushes the card wider than the viewport, and
   scrolls the whole page sideways on a phone — which is the defect the browser
   tier caught the last two times a wide thing landed on a page. */
.token {
  margin: 0 0 8px;
  padding: 10px 12px;
  background: var(--amber-bg);
  border: 1px solid var(--amber);
  border-radius: 6px;
  overflow-wrap: anywhere;
  font-size: 13px;
}

/* The workflow's moves: one form each, stacked on a phone and in a row where
   there is room. A reason box takes the full width of its move, because a
   reason typed into a sliver is a reason nobody finishes writing. */
.moves {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 0 0 12px;
}

.move {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1 1 220px;
}

.move textarea {
  width: 100%;
  box-sizing: border-box;
}

/* A case's history. Reasons are people's words, so they wrap anywhere rather
   than pushing the card wider than the screen. */
.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.timeline li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.timeline-reason {
  overflow-wrap: anywhere;
  font-size: 13px;
}

@media (max-width: 720px) {
  .facts.tight {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --- Quality and integrity -------------------------------------------------
 *
 * Three figures across, collapsing to one column on a phone like every other
 * grid here. A `dl` rather than a table: these are three readings of one
 * window, not rows to be compared down a column.
 */
.kpis {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px 16px;
  padding: 16px;
  margin: 0;
}

.kpi {
  min-width: 0;
}

.kpi .caption {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
  overflow-wrap: anywhere;
}

.kpi .figure {
  margin: 0;
  font-size: 26px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--navy);
}

/* What a measure does and does not establish, printed in the same card as the
 * figure rather than in a footnote. A number on a page headed "integrity" is
 * read as an accusation, and the sentence bounding it has to be as hard to miss
 * as the number. */
.limits {
  padding: 12px 16px 16px;
  border-top: 1px solid var(--rule);
  font-size: 12.5px;
  color: var(--muted);
}

.limits p {
  margin: 0 0 6px;
  overflow-wrap: anywhere;
}

.limits p:last-child {
  margin-bottom: 0;
}

.limits strong {
  color: var(--ink);
}

@media (max-width: 720px) {
  .kpis {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── The platform console (ADR-0006) ─────────────────────────────────────
   One page wide and no sidebar: an operator's screen is not an agency's, and
   should not look like one. */
.console {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px 16px;
}

.console-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.console-nav,
.console-head form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
/* Setting up a field phone: the QR code beside the three steps it starts
   (devices.html), and the same steps on the page the link opens without the
   app (device_setup.html). The QR code is inline SVG with no size of its own,
   so it is sized here -- large enough for a budget phone's camera across a
   desk, never wider than the card on a phone. */
.setup {
  display: flex;
  gap: 24px;
  align-items: center;
  padding: 18px 20px 4px;
  flex-wrap: wrap;
}
.setup-qr {
  flex: 0 0 auto;
  width: 220px;
  max-width: 100%;
  padding: 10px;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
}
.setup-qr svg.qr {
  display: block;
  width: 100%;
  height: auto;
}
.setup-steps {
  flex: 1 1 260px;
  margin: 0;
  padding-left: 22px;
  color: var(--ink);
  line-height: 1.5;
}
.setup-steps li {
  margin: 0 0 12px;
}
.signin-card .setup-steps {
  margin: 18px 0 8px;
  text-align: left;
}
.setup-card .token code {
  word-break: break-all;
}
