/* 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: #f3f5f8;
  --white: #fff;
  /* Surfaces told apart by tint rather than by lines, as the field app does
   * (`android/.../ui/Theme.kt`): direction A, approved 6 October 2026. */
  --tint-1: #f8fafc;
  --tint-2: #eef2f6;
  --tint-3: #e5eaf0;
  --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.05), 0 2px 8px rgba(16, 35, 63, 0.04);
  /* The field app's corners: 10px small, 16px for a surface, 22px for the one
   * card that leads a page. */
  --r: 16px;
  --r-sm: 10px;
  --r-lg: 22px;
  /* 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: 15px;
  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: 12px;
  color: #8a9bb1;
  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: #fff;
}

.nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #c7d0dc;
  text-decoration: none;
  font-size: 13.5px;
  /* Inset and rounded, as the field app marks the tab it is on: no band down
   * the edge (direction A, 7 October 2026). */
  margin: 1px 10px;
  padding: 8px 10px;
  border-radius: var(--r-sm);
}

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

.nav a[aria-current="page"] {
  background: rgba(255, 255, 255, 0.12);
  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: transparent;
  padding: 22px 24px 6px;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.top h2 {
  font-size: 25px;
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--navy);
}

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

.top .spacer {
  flex: 1;
}

/* The box at the top of every page that finds a case (`api/find_box.py`). A
 * plain bar above the page's header: one line at every width, the input taking
 * what the label and the button leave, so it never pushes the page sideways. */
.find-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--white);
  border-bottom: 1px solid var(--rule);
  padding: 8px 22px;
}

/* The shared field, laid on one line: its label beside the box rather than
 * above it, and visible at every width (UI standard: a label is always
 * visible). */
.find-bar .field {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
}

.find-bar .field .field-head {
  margin-bottom: 0;
}

.find-bar .field .field-head label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--navy);
  white-space: nowrap;
}

.find-bar input {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 620px;
  font: inherit;
  font-size: 14px;
  padding: 8px 12px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--tint-2);
  color: var(--ink);
}

.find-bar input:focus {
  background: var(--white);
  border-color: var(--blue);
}

@media (max-width: 760px) {
  .find-bar {
    padding: 6px 12px;
  }

  /* On a phone the page's own heading comes first and the search box under
   * it: above it, the box pushed the heading 165px down under a closed menu,
   * past the 140px the sidebar test holds every page to (test_sidebar.py). */
  .main > .top {
    order: -1;
  }
}

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

/* A line said straight onto the page -- a way back, a note on a filter --
 * keeps its distance from the card beneath it. */
.wrap > p {
  margin: 0 0 14px;
}

/* 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: var(--r-sm);
  padding: 9px 16px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  text-decoration: none;
  display: inline-block;
  line-height: 1.6;
  /* 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: 6px 12px;
  font-size: 13px;
}

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

.card {
  background: var(--white);
  border: 0;
  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: 18px 20px 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

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

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

.card-b {
  padding: 12px 20px 18px;
}

/* 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 20px;
}

.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;
  /* The portal checklist prints a lender's portal address here, an unbroken
   * token that would otherwise push a 390px page sideways. */
  overflow-wrap: anywhere;
}

/* The set-up guide: a band above a set-up screen's own content, saying how far
 * set-up has got and where to go next (`api/setup_guide.py`). */
.guide {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  align-items: center;
  background: var(--white);
  border-radius: var(--r);
  box-shadow: var(--sh);
  margin: 10px 22px 0;
  padding: 12px 20px;
}

.guide-words {
  flex: 1 1 260px;
  min-width: 0;
  font-size: 12.5px;
}

.guide-words strong {
  display: block;
  color: var(--navy);
  font-size: 13.5px;
}

.guide-count {
  display: block;
  font-size: 12.5px;
  color: var(--muted);
  font-weight: 500;
}

/* --- Getting started (`getting_started.html`) -------------------------------
 *
 * One card saying what to do next, then the stages. It is the case page's
 * Next card -- white, lifted, with the one amber button on the page -- so the
 * thing to do next looks the same wherever it is said (direction A). */
.start-next {
  background: var(--white);
  color: var(--ink);
  border-radius: var(--r-lg);
  box-shadow: var(--sh);
  padding: 20px 22px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px 22px;
  align-items: center;
  margin-bottom: 16px;
}

.start-next-words {
  flex: 1 1 260px;
  min-width: 0;
}

.start-eyebrow {
  font-size: 12.5px;
  color: var(--muted);
  font-weight: 500;
}

.start-next h3 {
  font-size: 20px;
  font-weight: 650;
  color: var(--navy);
  margin-top: 2px;
}

.start-next p,
.start-next .tiny {
  color: var(--muted);
  font-size: 14px;
}

.start-count {
  text-align: right;
}

.start-count strong {
  display: block;
  color: var(--navy);
  font-size: 22px;
  font-variant-numeric: tabular-nums;
}

.start-count span {
  font-size: 12.5px;
  color: var(--muted);
}

.start-complete {
  background: var(--green-bg);
}

.start-complete h3,
.start-complete .start-count strong {
  color: var(--green);
}

.start-stage {
  margin-bottom: 16px;
}

/* A fact about the installation nobody here can change: said, not a step. */
.start-note {
  margin-bottom: 16px;
}

.start-number {
  width: 24px;
  height: 24px;
  border-radius: 7px;
  background: var(--navy);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  display: grid;
  place-items: center;
  flex: none;
}

.start-steps {
  list-style: none;
}

.start-step {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: flex-start;
  padding: 14px 20px;
}

.start-step + .start-step {
  border-top: 1px solid var(--tint-2);
}

.start-now {
  background: var(--amber-bg);
}

.start-mark {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--rule);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  flex: none;
  margin-top: 1px;
}

.start-done .start-mark {
  background: var(--green);
  border-color: var(--green);
}

.start-now .start-mark {
  border-color: var(--amber);
  background: #fff;
}

.start-words {
  flex: 1 1 220px;
  min-width: 0;
}

.start-words strong {
  display: block;
  color: var(--navy);
  font-size: 13.5px;
}

.start-found {
  color: var(--green);
  font-size: 12.5px;
  font-weight: 600;
}

.start-act {
  display: flex;
  align-items: center;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 99px;
  font-size: 12.5px;
  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: var(--tint-2);
  color: var(--muted);
}

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

/* A link in running text. Never the browser's own blue and heavy underline. */
a {
  color: var(--blue);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

/* ---------- 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: 4px 20px 10px;
  text-align: left;
}

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

th {
  text-align: left;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 650;
  padding: 10px 14px;
  border-bottom: 1px solid var(--rule);
  background: transparent;
}

td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--tint-2);
  font-size: 14px;
  vertical-align: middle;
}


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

/* At a desk a table in a card lines up with the card's own 20px edge; on a
 * phone its rows stack into cards of their own and keep their padding. */
@media (min-width: 761px) {
  .card th:first-child,
  .card td:first-child {
    padding-left: 20px;
  }

  .card th:last-child,
  .card td:last-child {
    padding-right: 20px;
  }
}

/* --- 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: var(--tint-1);
}

/* 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. */
/* A link in a table names the thing on its row: navy and bold, underlined
 * only under the pointer, as a row link is. */
td a:not(.btn):not(.pill) {
  color: var(--navy);
  font-weight: 600;
  text-decoration: none;
}

td a:not(.btn):not(.pill):hover {
  text-decoration: underline;
}

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: 12.5px;
}

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

.right {
  text-align: right;
}

/* A column of figures: right-aligned in figures of one width, its heading
 * above it, so totals can be read down the column. */
td.num,
th.num {
  text-align: right;
}

/* One line for a figure where there is room; on a phone a cell may wrap, or a
 * long one would take the page sideways (a report row at 150%, 7 Oct). */
@media (min-width: 761px) {
  td.num {
    white-space: nowrap;
  }
}

/* ---------- tabs ---------- */
.tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.tabs a {
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  padding: 8px 14px;
  font-size: 14px;
  color: var(--muted);
  text-decoration: none;
  font-family: inherit;
  font-weight: 600;
}

.tabs a:hover {
  background: var(--tint-2);
}

.tabs a[aria-current="page"] {
  color: var(--navy);
  background: var(--white);
  box-shadow: var(--sh);
}

/* ---------- the case file ----------
 * A stage strip, the next step, a folded "More" and one open section
 * (`case_layout.py`). Plain: rules and words, no coloured bands. */
.stage-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  list-style: none;
  margin: 0 0 16px;
  padding: 4px;
  border-radius: var(--r-sm);
  background: var(--tint-2);
  overflow: hidden;
}

.stage-strip li {
  flex: 1 0 auto;
  padding: 7px 12px;
  font-size: 13px;
  color: var(--muted);
  border-radius: 7px;
  white-space: nowrap;
  text-align: center;
}

.stage-strip li.done {
  color: var(--ink);
}

.stage-strip li.now {
  color: #fff;
  background: var(--navy);
  font-weight: 600;
}

.more > summary {
  cursor: pointer;
  padding: 12px 18px;
  font-weight: 600;
  color: var(--navy);
}

.more-body {
  display: grid;
  gap: 16px;
  padding-top: 0;
}

.more-part + .more-part,
.more-body > form {
  border-top: 1px solid var(--rule);
  padding-top: 12px;
}

.more-h h3 {
  font-size: 13px;
  margin: 0 0 8px;
}

.tab-panel[hidden] {
  display: none;
}

/* The work on the left, a glance on the right; one column below a desk. */
.case-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

.case-main,
.case-side {
  min-width: 0;
}

.case-side {
  display: grid;
  gap: 16px;
}

@media (width > 1100px) {
  .case-grid {
    grid-template-columns: minmax(0, 1fr) 300px;
  }
}

meter.used {
  display: block;
  width: 100%;
  height: 8px;
}

.recent {
  list-style: none;
  margin: 0;
  padding: 0 18px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.recent li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  overflow-wrap: anywhere;
}

.case-tabs {
  margin-top: 16px;
}

/* The number beside a section that holds a list, quieter than its name. */
.case-tabs .n {
  font-weight: 400;
  color: var(--muted);
  margin-left: 4px;
}

/* The status bar under the name: no header rule, because the bar is the card. */
.case-head .card-h {
  border-bottom: 0;
}

.case-head .refused {
  margin: 0 16px 12px;
}

/* A stage already passed is ticked, as the mock has it. */
.stage-strip li.done::before {
  content: "\2713\00a0";
  color: var(--green);
}

/* The Next card says what to do in words before it offers buttons. */
.next-card > .next-head {
  display: grid;
  gap: 6px;
}

.next-head .eyebrow {
  font-size: 12.5px;
  color: var(--muted);
}

.next-title {
  font-size: 18px;
  color: var(--navy);
  margin: 0;
}

.meter-row {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  font-size: 13px;
}

.meter-row strong {
  color: var(--navy);
}

/* ---------- callouts ---------- */
.note {
  background: var(--blue-bg);
  padding: 12px 14px;
  border-radius: var(--r-sm);
  font-size: 13.5px;
  color: #1e4e7c;
}

/* Nothing to show: a quiet tinted panel inside the card, as the field app
 * says it, rather than a tall white gap (direction A). */
.empty {
  padding: 22px 20px;
  margin: 6px 20px 18px;
  background: var(--tint-1);
  border-radius: 12px;
  text-align: center;
  color: var(--muted);
}

.card-b > .empty {
  margin: 0;
}

.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. A block, because a
     * table's header group ignores `overflow`, so its headings still widened
     * the page (Assign cases, 7 October 2026). */
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  tbody tr {
    border: 0;
    border-radius: 12px;
    margin: 8px 12px;
    padding: 6px 0;
    background: var(--tint-1);
    /* `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(--tint-1);
  }

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

  /* A pill that says a sentence wraps inside its cell rather than taking the
   * page sideways. */
  td .pill {
    white-space: normal;
  }

  td::before {
    content: attr(data-label);
    flex: 0 0 96px;
    font-size: 12.5px;
    color: var(--muted);
    font-weight: 500;
  }

  /* Several pieces in one cell, kept as one block beside the label so they
   * wrap as text does; laid out as flex items they never wrap at all. */
  .cell-stack {
    min-width: 0;
  }

  .cell-stack > * {
    margin-right: 6px;
  }

  /* 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;
  }

  /* The queue on a phone reads as the field app's case list: the reference and
   * how the clock stands on the first line, then who it is about, then what
   * kind of work it is and where it has got to -- one short card, not ten
   * labelled lines (direction A, 7 October 2026). */
  .queue tbody tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "ref clock"
      "who clock"
      "type type"
      "lref lref"
      "stage stage";
    gap: 2px 12px;
    padding: 12px 14px;
  }

  .queue td {
    display: block;
    padding: 0;
  }

  .queue td::before {
    content: none;
  }

  .queue td[data-label="Case"] { grid-area: ref; }
  .queue td[data-label="Applicant"] { grid-area: who; }
  .queue td[data-label="Type"] { grid-area: type; color: var(--muted); font-size: 13px; }
  .queue td[data-label="Lender ref."] { grid-area: lref; font-size: 12px; }
  .queue td[data-label="Stage"] { grid-area: stage; margin-top: 6px; }

  .queue td[data-label="Turnaround"] {
    grid-area: clock;
    text-align: right;
  }

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

  .pager {
    flex-wrap: wrap;
  }

  /* A button in a card wraps rather than running over the cells beside it: at
   * 260px "Deliver through the portal" stood past its cell and the "Format
   * version" cell lay over it, so the tap never landed (round 2, DB-06). */
  td .btn {
    white-space: normal;
    text-align: left;
  }
}

/* **A phone zoomed to 150% is 260px wide**, and a 96px label beside each value
 * left the value too little room: a date broke to one character per line and
 * the card ran past the screen (round 2, DB-06). Below 360px the label sits
 * above its value instead, so the value has the whole card's width. */
@media (max-width: 360px) {
  td {
    display: block;
  }

  td::before {
    display: block;
    margin-bottom: 2px;
  }
}

@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: #c7d0dc;
    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 {
    white-space: nowrap;
    margin: 2px 4px;
  }

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

  .guide {
    margin: 10px 14px 0;
  }
}

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

/* ---------- the front page ----------
 * Where everybody starts (`sign_in.html`). The sign-in card is the standalone
 * pages' own, unchanged, so the door somebody uses every morning looks as it
 * did; what is new sits beside and beneath it. Its own body class rather than
 * `.signin-page`, which centres one card on the navy field and is shared with
 * the set-up, device and error pages.
 */
.front-page {
  background: var(--navy);
  height: auto;
  min-height: 100%;
}

.front {
  max-width: 1120px;
  margin: 0 auto;
  padding: 28px 20px 40px;
}

.front-doors {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px;
  align-items: start;
}

.front-door {
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.06);
  border-radius: var(--r);
  padding: 22px 20px;
  color: #fff;
}

/* A label over a panel: the panel's own colour, quieter. Amber is kept for
 * the one thing to press (direction A; no amber eyebrows, 3 October). */
.front-tag {
  display: block;
  font-size: 13px;
  color: inherit;
  opacity: 0.72;
  font-weight: 600;
}

.front-door h2 {
  font-size: 18px;
  margin-top: 6px;
}

.front-door p {
  color: #c4d0e2;
  font-size: 13px;
  margin: 6px 0 14px;
}

.front-light {
  background: #fff;
  color: var(--navy);
}

.front-light:hover {
  background: var(--paper);
}

.front-sheet {
  background: var(--paper);
  border-radius: var(--r);
  margin-top: 22px;
  padding: 24px 22px 28px;
}

.front-h {
  font-size: 16px;
  font-weight: 650;
  color: var(--navy);
}

.front-tiles {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  margin-top: 12px;
}

.front-tiles li {
  background: var(--white);
  border-radius: var(--r);
  box-shadow: var(--sh);
  padding: 16px;
}

.front-ico {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 11px;
  background: var(--amber-bg);
}

.front-ico svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: var(--amber-d);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.front-tiles strong {
  display: block;
  color: var(--navy);
  font-size: 16px;
  margin-top: 10px;
}

.front-tiles li > span:last-child {
  font-size: 13px;
}

.front-walk {
  display: flex;
  flex-wrap: wrap;
  gap: 24px 32px;
  align-items: center;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  box-shadow: var(--sh);
  padding: 22px;
  margin-top: 22px;
}

.front-how {
  flex: 1 1 300px;
  min-width: 0;
}

.front-device {
  flex: none;
  width: 210px;
  height: 380px;
  margin: 0 auto;
  border-radius: 28px;
  background: var(--navy);
  padding: 10px;
  box-shadow: 0 10px 30px rgba(16, 35, 63, 0.18);
}

.front-screen {
  position: relative;
  height: 100%;
  border-radius: 20px;
  background: var(--paper);
  overflow: hidden;
}

/* Four scenes on one timeline of twenty-four seconds, each on stage for a
 * quarter of it. One set of keyframes and four delays, so the scenes and the
 * steps beside them cannot drift apart. */
.front-scene {
  position: absolute;
  inset: 0;
  padding: 30px 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  opacity: 0;
  animation: front-turn 24s infinite;
}

/* Negative delays: every scene is already part-way through the one cycle when
 * the page is drawn, so nothing waits blank for its turn and no two are on
 * stage together. The steps' selector carries `.front-steps` so the delay outranks
 * the shorthand on `.front-steps li`, which would otherwise reset it to nought and
 * light all four at once. */
.front-s2,
.front-steps .front-b2 {
  animation-delay: -18s;
}

.front-s3,
.front-steps .front-b3 {
  animation-delay: -12s;
}

.front-s4,
.front-steps .front-b4 {
  animation-delay: -6s;
}

.front-brand {
  font-weight: 700;
  color: var(--navy);
  font-size: 15px;
}

.front-label {
  font-size: 10.5px;
  font-weight: 600;
  color: var(--navy);
  margin-top: 4px;
}

.front-box {
  border: 1.5px solid var(--rule);
  border-radius: 7px;
  background: var(--white);
  padding: 6px 8px;
  min-height: 30px;
  font-family: "Cascadia Mono", Consolas, monospace;
  font-size: 12px;
}

/* Typed a character at a time: the width grows in steps of one character of a
 * fixed-width face, on the same timeline as the scene it sits in. */
.front-typed {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
  width: 11ch;
  animation: front-type-first 24s steps(11, end) infinite;
  animation-delay: -18s;
}

.front-t2 {
  animation-name: front-type-second;
}

.front-fake {
  background: var(--amber);
  color: var(--navy);
  border-radius: 7px;
  text-align: center;
  padding: 8px;
  font-weight: 700;
  font-size: 11.5px;
  margin-top: 6px;
}

.front-dim {
  opacity: 0.45;
}

.front-tap {
  animation: front-press 2.4s ease-in-out infinite;
}

.front-pulse,
.front-tick {
  display: grid;
  place-items: center;
  width: 70px;
  height: 70px;
  border-radius: 50%;
  margin: 34px auto 6px;
  font-size: 32px;
}

.front-pulse {
  background: var(--blue-bg);
  color: var(--blue);
  animation: front-ring 2.2s ease-out infinite;
}

.front-tick {
  background: var(--green);
  color: #fff;
}

.front-s3,
.front-s4 {
  text-align: center;
}

.front-note {
  font-size: 11.5px;
  color: var(--muted);
}

.front-steps {
  list-style: none;
  counter-reset: front;
  margin-top: 10px;
}

.front-steps li {
  counter-increment: front;
  position: relative;
  padding: 10px 12px 10px 48px;
  border-radius: 10px;
  animation: front-lit 24s infinite;
}

.front-steps li::before {
  content: counter(front);
  position: absolute;
  left: 12px;
  top: 10px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid var(--rule);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  background: var(--white);
}

.front-steps strong {
  display: block;
  color: var(--navy);
  font-size: 14px;
}

.front-steps span {
  font-size: 12.5px;
  color: var(--muted);
}

.front-faq {
  margin-top: 22px;
}

.front-faq details {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 11px 14px;
  margin-top: 8px;
}

.front-faq summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--navy);
  font-size: 13.5px;
}

.front-faq p {
  margin-top: 6px;
  font-size: 13px;
}

@keyframes front-turn {
  0%,
  23% {
    opacity: 1;
  }
  25%,
  98% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes front-lit {
  0%,
  23% {
    background: var(--amber-bg);
  }
  25%,
  100% {
    background: transparent;
  }
}

/* On the second scene's own clock: the mobile in its first third, the code in
 * its second, both standing for the rest of its turn. */
@keyframes front-type-first {
  0%,
  1% {
    width: 0;
  }
  8%,
  100% {
    width: 11ch;
  }
}

@keyframes front-type-second {
  0%,
  10% {
    width: 0;
  }
  17%,
  100% {
    width: 11ch;
  }
}

@keyframes front-press {
  50% {
    box-shadow: 0 0 0 5px rgba(232, 163, 61, 0.3);
  }
}

@keyframes front-ring {
  0% {
    box-shadow: 0 0 0 0 rgba(42, 111, 176, 0.45);
  }
  100% {
    box-shadow: 0 0 0 16px rgba(42, 111, 176, 0);
  }
}

/* With motion reduced nothing plays: the written steps are the whole of it,
 * and the picture shows the one scene where something is typed. */
@media (prefers-reduced-motion: reduce) {
  .front-scene,
  .front-typed,
  .front-tap,
  .front-pulse,
  .front-steps li {
    animation: none;
  }

  .front-s2 {
    opacity: 1;
  }
}

/* ---------- 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;
  justify-content: center;
  /* **Never `align-items: center` here, and never a fixed height.** `body` is
     `height: 100%`, so a centred child taller than the viewport has its overflow
     split between both ends -- and the half above the top is not scrollable, so
     the heading and the language row simply cannot be reached. The download page
     is the first thing on this layout tall enough to show it. `margin: auto` on
     the child centres it exactly as before while there is room, and resolves to
     nought when there is not, which leaves the top reachable. */
  height: auto;
  min-height: 100%;
  padding: 24px;
}

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

.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: 13px;
  color: var(--muted);
  font-weight: 600;
}

.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 {
  margin: 22px 0;
}

.signin-by span {
  display: block;
  font-size: 12.5px;
  color: var(--muted);
}

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

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

/* A line of a sign-in card followed by another keeps its distance: on the
 * error page the button sat against the reference above it. */
.signin-card > p + p {
  margin-top: 14px;
}

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

.signin-msg {
  margin-top: 14px;
  background: var(--red-bg);
  padding: 10px 13px;
  border-radius: var(--r-sm);
  font-size: 13.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. */
/* A textarea was the one control the stylesheet did not draw inside a field:
 * a browser's own box in the middle of a styled form (26 Sep 2026). */
.field textarea {
  /* As tall as what is written in it, as the field app's boxes are: an answer
   * of three words no longer sits in a box drawn for a paragraph. A browser
   * without `field-sizing` keeps the box's own rows. */
  field-sizing: content;
  min-height: 2.9rem;
  max-height: 18rem;
  resize: vertical;
  line-height: 1.45;
}

.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.
 *
 * **The panel hangs from the row the ⓘ sits in, not from the ⓘ itself.** It
 * used to be 22rem wide from the ⓘ's own left edge, so an ⓘ beside a label
 * two hundred pixels in, on a 390px phone, opened a panel past the screen's
 * right edge and the page scrolled sideways. The label row and the card
 * heading are as wide as what holds them, so a panel spanning either stays
 * inside it. */
.field-head,
.card-h {
  position: relative;
}

.info {
  position: static;
}

.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: 0;
  right: 0;
  max-width: 26rem;
  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;
}

/* A heading inside a form that groups the boxes beneath it -- "Primary
 * address" -- spanning the row so the boxes start on a line of their own. */
.form-part {
  grid-column: 1 / -1;
  margin: 4px 0 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--navy);
}

/* A part of a form a person opens only when they need it: another address.
 * Its summary reads as the action it is. */
.form-more {
  padding: 0 16px 8px;
  max-width: 720px;
}

.form-more > summary {
  cursor: pointer;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--navy);
  padding: 8px 0;
}

.form-more > .form-grid {
  padding: 8px 0 0;
}

.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: 13.5px;
  font-weight: 600;
  color: var(--navy);
  margin-bottom: 6px;
}

.field .hint {
  display: block;
  font-size: 12.5px;
  color: var(--muted);
  font-weight: 400;
  margin-top: 4px;
  /* 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="search"],
.field input[type="tel"],
.field input[type="date"],
.field input[type="number"],
.field select,
.field textarea {
  width: 100%;
  font-family: inherit;
  font-size: 15px;
  color: var(--ink);
  background: var(--tint-2);
  border: 1px solid transparent;
  border-radius: 12px;
  padding: 10px 13px;
}

.field input[type="text"]:hover,
.field input[type="email"]:hover,
.field input[type="search"]:hover,
.field input[type="tel"]:hover,
.field input[type="date"]:hover,
.field input[type="number"]:hover,
.field select:hover,
.field textarea:hover {
  border-color: var(--rule);
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  background: var(--white);
  border-color: var(--blue);
}

/* The file chooser's own button, drawn like the product's quiet buttons rather
 * than the browser's grey one. */
.field input[type="file"]::file-selector-button {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--navy);
  background: var(--tint-2);
  border: 0;
  border-radius: var(--r-sm);
  padding: 8px 14px;
  margin-right: 12px;
  cursor: pointer;
}

.field input[type="file"]::file-selector-button:hover {
  background: var(--tint-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(--tint-3);
  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(--tint-2);
  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,
.filters .field.size-inline {
  display: flex;
  align-items: center;
  gap: 8px;
}

.filters .field.inline label,
.filters .field.size-inline .field-head label,
.filters .field.size-inline .check label {
  margin: 0;
  white-space: nowrap;
}

.filters .field.size-inline .field-head {
  margin-bottom: 0;
}

/* On a phone the filter bar wrapped wherever each control's width happened to
   fall (F40). Laid out instead as two rows of choosers, each a whole line with
   its label in a fixed column, the two ticks side by side between them, and the
   buttons together at the foot. */
@media (max-width: 760px) {
  .filters {
    display: grid;
    /* `minmax(0, …)`: a bare `1fr` never shrinks below its content, and a
     * chooser's content is as wide as its longest option (260px, 7 Oct). */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 12px;
    align-items: center;
  }

  .filters .field {
    min-width: 0;
  }

  .filters .field.size-inline .check label {
    white-space: normal;
  }

  .filters .field.size-inline:has(select) {
    grid-column: 1 / -1;
  }

  .filters .field.size-inline:has(select) .field-head {
    flex: 0 0 56px;
  }

  .filters .field.size-inline select {
    flex: 1 1 auto;
    min-width: 0;
    width: auto;
  }

  .filters > .btn {
    justify-self: stretch;
    text-align: center;
    /* A button that names a page ("Visits made, by executive") wraps here
     * rather than spilling past its column. */
    white-space: normal;
  }
}

/* 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;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 14px 20px 18px;
  border-radius: 0 0 var(--r) var(--r);
}

/* A save said beside the thing saved: `.refused`'s shape in green, so a person
   sees the save happened rather than inferring it from the page reloading. */
.saved {
  margin: 0 0 8px;
  padding: 10px 14px;
  border: 0;
  background: var(--green-bg);
  color: var(--green);
  border-radius: var(--r-sm);
  font-size: 13.5px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

/* 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 20px 0;
  padding: 11px 14px;
  border: 0;
  background: var(--red-bg);
  color: var(--red);
  border-radius: var(--r-sm);
  font-size: 13.5px;
  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="search"],
.field.bad input[type="tel"],
.field.bad input[type="date"],
.field.bad input[type="number"],
.field.bad select,
.field.bad textarea {
  border-color: var(--red);
  background: var(--red-bg);
}

/* A refused box says why beneath it, where its hint would be, so several
 * refusals can be read at once beside the boxes they belong to. */
.field.bad .hint {
  color: var(--red);
}

/* 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 .optional {
  font-weight: 400;
  color: var(--muted);
}

.choice-set legend {
  font-size: 13.5px;
  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 20px;
  margin: 0;
  font-size: 13px;
  color: var(--muted);
}

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

/* A note's list keeps its bullets inside the card (vetting, 5 Oct). */
.card-note ul {
  margin: 4px 0 0;
  padding-left: 18px;
}

.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 20px;
  margin: 0;
}

/* Inside a card's body the body already holds the card's edge. */
.card-b > .facts {
  padding-left: 0;
  padding-right: 0;
}

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

.facts dt {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 2px;
}

.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(--tint-2);
}

/* The sentences under a row's heading sit inside the card's edge, as the
   heading does; on the case file they touched the border (vetting, 5 Oct).
 *
 * A record's folds sit on one row as chips rather than a line each (direction
 * A, 7 October 2026): People drew six folded lines for every person, so the
 * page ran to 23,502px. Everything else in the record keeps a line of its own;
 * a fold that is opened moves below the chips and takes the full width, so its
 * form reads as the row's own and the chips stay together. */
.rel {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  column-gap: 8px;
  padding: 0 20px 14px;
}

.rel > * {
  flex: 1 0 100%;
  min-width: 0;
}

/* The record's own edge is the list item's, so nothing inside adds its own. */
.rel > .rel-h,
.rel > p,
.rel > .rel-note,
.rel > .facts,
.rel > .facts.tight,
.rel > .refused {
  padding-left: 0;
  padding-right: 0;
  margin-left: 0;
  margin-right: 0;
}

.rel > p {
  margin: 4px 0 0;
  padding: 0 20px;
}

.rel-h {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  padding: 16px 20px 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;
}

/* A one-line form inside a row -- a list row's heading, a table cell, a card
 * heading: its label beside the box (`size="inline"`), then the button. It
 * wraps where the row is narrow, so nothing is pushed past a phone's edge. */
form.row-action {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  min-width: 0;
}

.row-action .field.size-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
  min-width: 0;
  max-width: 100%;
}

.row-action .field.size-inline .field-head {
  margin-bottom: 0;
}

.row-action .field.size-inline .field-head label {
  margin: 0;
  font-size: 12.5px;
  white-space: nowrap;
}

.row-action .field.size-inline input[type="text"],
.row-action .field.size-inline select {
  width: 14rem;
  max-width: 100%;
  min-width: 0;
  padding: 7px 10px;
}

/* A table of boxes (the adjusted figures): the column heading and the line's
 * name label each box where it can be seen, so the field's own label is kept
 * for a screen reader and hidden from sight. */
.figures .field {
  margin: 0;
  min-width: 0;
}

.figures .field-head {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 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 20px 0;
  color: var(--muted);
}

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

@media (max-width: 720px) {
  .facts.tight {
    grid-template-columns: repeat(2, 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);
}

/* A fold: a chip that opens its form beneath it. */
.rel-edit {
  margin: 10px 16px 4px;
}

.rel > .rel-edit {
  order: 1;
  flex: 0 0 auto;
  margin: 10px 0 0;
}

.rel > .rel-edit[open] {
  order: 2;
  flex: 1 0 100%;
  margin: 12px 0 0;
}

.rel-edit summary {
  cursor: pointer;
  display: inline-block;
  list-style: none;
  padding: 5px 12px;
  border-radius: 99px;
  background: var(--tint-2);
  font-size: 13px;
  font-weight: 600;
  color: var(--navy);
}

.rel-edit summary::-webkit-details-marker {
  display: none;
}

.rel-edit summary:hover {
  background: var(--tint-3);
}

.rel-edit[open] {
  background: var(--tint-1);
  border-radius: 12px;
  padding: 10px 16px 4px;
}

.rel-edit[open] summary {
  background: var(--white);
  box-shadow: var(--sh);
}

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

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

/* A firm's seal and signature on file (`0112`), at about the size a report
   draws it, and never wider than a phone's column. */
.seal-preview {
  display: block;
  max-width: min(160px, 100%);
  max-height: 108px;
  margin: 10px 0 0;
  border: 1px solid var(--rule);
  background: var(--white);
}

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

/* A refusal with several reasons: the line saying what they are, then a short
   list (`_forms.told`). */
.refused p {
  margin: 0;
}
.refused ul {
  margin: 6px 0 0;
  padding-left: 18px;
}

/* 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;
  align-items: flex-start;
  gap: 12px;
  margin: 0 0 12px;
}

.move {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  flex: 1 1 220px;
  /* A form is at most 720px wide (docs/UI-STANDARD.md). */
  max-width: 720px;
}

/* The forms folded under More, held to the same width. */
.more-body form {
  max-width: 720px;
}

/*
 * No field on the case file is wider than 720px (docs/UI-STANDARD.md). Vetting
 * found ten add forms -- a person, a borrowing, a check, a visit -- stretched
 * across a 1,500px card, and capping the form left the unpadded ones under More
 * 20px over, so the fields themselves carry the limit. A form that holds a
 * table (the assessor's figures) keeps the width the table needs.
 */
:where(.case-main .card form:not(:has(table))) :is(input, select, textarea) {
  max-width: 720px;
}

.next-go {
  padding-top: 0;
}

/* The moves sit inside the card's edge, under its words. */
.next-card > .moves {
  padding: 0 20px;
}

/* A send-back fold sits in the row of moves as a chip, on the row's own edge. */
.moves > .rel-edit {
  margin: 0;
}

/*
 * On a phone the strip shows where the case is: the last stage passed, the one
 * it is at and the next, on one row rather than three (vetting, 5 Oct). The
 * sections scroll sideways in one row, as the mock has them.
 */
@media (max-width: 760px) {
  .stage-strip {
    flex-wrap: nowrap;
  }

  .stage-strip li.done:has(+ li.done),
  .stage-strip li.now ~ li ~ li {
    display: none;
  }

  .stage-strip li {
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .case-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .case-tabs a {
    flex: 0 0 auto;
    white-space: nowrap;
  }
}

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

/* A move's button is as wide as its words, as the mock has it; stretched to
   the form's width, "Close the case" was a bar across half the card. */
.move > .btn {
  align-self: flex-start;
}

/* 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;
}

/* A history written straight into a card has the room a bare paragraph is
   given (F39): it sat against the card's border, which a phone makes plain. */
.card > .timeline {
  padding: 12px 16px;
}

.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);
  }
}

/* --- My work ------------------------------------------------------------------
 *
 * The landing page from the approved mock (`api/my_work.py`): figures as tiles
 * that open the queue narrowed to them, and case rows that open wherever they
 * are clicked. The row's one link is the applicant's name, stretched over the
 * row by `::after`; the action button sits above it, so a keyboard and a screen
 * reader still meet one link per row.
 */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.tile {
  display: grid;
  gap: 2px;
  min-width: 0;
  background: var(--white);
  border-radius: var(--r);
  padding: 14px 16px;
  color: inherit;
  text-decoration: none;
  box-shadow: var(--sh);
}

.tile:hover {
  background: var(--tint-1);
}

.tile .k {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.tile b {
  font-size: 28px;
  line-height: 1.15;
  color: var(--navy);
}

.tile.alert b {
  color: var(--red);
}

.tile .d {
  font-size: 13px;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.work-list {
  list-style: none;
  margin: 0;
  padding: 6px 12px 12px;
  display: grid;
  gap: 6px;
}

.work-row {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 12px;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-radius: var(--r-sm);
  background: var(--tint-1);
}

.work-row:hover {
  background: var(--tint-2);
}

.work-row:has(.work-open:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.work-main {
  min-width: 0;
  flex: 1 1 220px;
}

.work-open {
  font-weight: 600;
  font-size: 16px;
  color: var(--ink);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.work-open:focus-visible {
  outline: none;
}

.work-open::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.work-side {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.work-side .btn {
  position: relative;
  z-index: 1;
}

/* A table whose every row opens its case wherever it is clicked (W2): the case
 * link already in the row (`.row-link`) is stretched over the row, and anything
 * else the row holds -- a button, a chooser, a form, another link -- sits above
 * it and keeps doing its own job. Measured in Chromium: a stretched link over a
 * table row covers the other cells. */
table.rows-open tbody tr {
  position: relative;
}

table.rows-open tbody tr:hover > td {
  background: var(--tint-1);
}

table.rows-open .row-link::after {
  content: "";
  position: absolute;
  inset: 0;
}

table.rows-open .row-link:focus-visible {
  outline: none;
}

table.rows-open tbody tr:has(.row-link:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

table.rows-open :is(button, select, input, textarea, label, a:not(.row-link)) {
  position: relative;
  z-index: 1;
}

/* --- 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: 12px;
  padding: 12px 20px 18px;
  margin: 0;
}

/* Each figure a tinted tile, as the field app shows a count. */
.kpi {
  min-width: 0;
  background: var(--tint-1);
  border-radius: 12px;
  padding: 12px 14px;
}

.kpi .caption {
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  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 20px 16px;
  border-top: 1px solid var(--tint-2);
  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) ─────────────────────────────────────
   Its own frame, from the approved mock (12 October 2026): a navy rail of the
   console's screens beside the page, never an agency's sidebar -- an operator
   is not in an agency, and the screens should not suggest it. The rail is drawn
   by `_nav.html`, which every signed-in page includes first inside `main`, so
   the frame is laid out here rather than repeated in each page. */
.console {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px 16px;
}

/* Laid out as a frame only where a page has the rail: a page showing a
   one-time link deliberately carries no links, and keeps the plain column. */
.console:has(> .console-rail) {
  display: grid;
  grid-template-columns: 224px minmax(0, 1fr);
  column-gap: 32px;
  align-items: start;
  max-width: none;
  margin: 0;
  min-height: 100vh;
  padding: 0 24px 48px 0;
}

.console:has(> .console-rail) > :not(.console-rail) {
  grid-column: 2;
  max-width: 1100px;
}

.console-nav.console-rail {
  grid-column: 1;
  grid-row: 1 / span 999;
  align-self: stretch;
  position: sticky;
  top: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  text-align: left;
  gap: 2px;
  padding: 20px 12px;
  background: var(--navy);
  color: #c9d5ec;
}

.console-brand {
  color: var(--white);
  font-weight: 700;
  padding: 0 10px 16px;
}

.console-brand small {
  display: block;
  font-weight: 500;
  color: #c9d5ec;
  font-size: 12px;
}

.console-rail > a {
  color: #c9d5ec;
  text-decoration: none;
  padding: 8px 10px;
  border-radius: 6px;
}

.console-rail > a:hover,
.console-rail > a:focus-visible {
  color: var(--white);
  background: rgb(255 255 255 / 8%);
}

.console-rail > a[aria-current="page"] {
  color: var(--white);
  background: rgb(255 255 255 / 14%);
  font-weight: 600;
}

.console-who {
  margin-top: auto;
  display: grid;
  gap: 4px;
  padding: 16px 10px 0;
  font-size: 13px;
}

.console-role {
  color: #9fb0d0;
}

.console-who .btn.ghost {
  color: var(--white);
  border-color: rgb(255 255 255 / 35%);
  justify-self: start;
}

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

/* A choice in a table row -- an operator's role -- drawn like the product's
   other controls rather than as the browser's bare dropdown. */
.console td select {
  font: inherit;
  padding: 6px 8px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--white);
}

.console td form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* A pill is one word or two; split mid-word it reads as two. */
.console .pill {
  white-space: nowrap;
}

/* What the agencies page counts, before the list: each state's agencies. */
/* A price plan's versions, as links across the top of its page (B5). */
.console-versions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 16px;
}

.console-versions > a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  color: var(--ink);
  text-decoration: none;
}

.console-versions > a[aria-current="page"] {
  border-color: var(--navy);
  font-weight: 600;
}

.console-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.console-tile {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 12px 14px;
}

.console-tile .k {
  color: var(--muted);
  font-size: 13px;
}

.console-tile .v {
  font-size: 22px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* A price plan's draft (14 October 2026, Devarajan's choice of the mock): the
   parts beside a column holding the part being added and what the plan would
   bill. Below 1100px the column follows the parts. */
.plan-build {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 24px;
  align-items: start;
}

.plan-side {
  display: grid;
  gap: 16px;
  position: sticky;
  top: 16px;
}

.plan-main > h3 {
  margin: 24px 0 8px;
}

/* The column is narrow: its forms take one box to a line. */
.plan-side .form-grid {
  grid-template-columns: minmax(0, 1fr);
}

.plan-side .card > .form-grid,
.plan-side .card > p,
.plan-side .card > .scroller {
  padding: 0 16px 16px;
}

/* The usual deals, and the kinds of part: plain cards, one choice each. */
.deal-cards,
.kind-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
  align-items: start;
  margin: 8px 0 20px;
}

.deal-card {
  display: grid;
  gap: 10px;
  align-content: start;
  padding: 14px;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--white);
}

.deal-card h4,
.deal-card p {
  margin: 0;
}

.deal-card .form-foot {
  margin-top: auto;
}

.kind-card {
  display: grid;
  gap: 2px;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  background: var(--white);
  color: var(--ink);
  text-decoration: none;
}

.kind-card span {
  color: var(--muted);
  font-size: 13px;
}

.kind-card:hover,
.kind-card:focus-visible {
  border-color: var(--navy);
}

/* Slabs as a small table of boxes, not a notation to learn. */
fieldset.slabs {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

fieldset.slabs legend {
  font-weight: 600;
  padding: 0;
  margin-bottom: 4px;
}

fieldset.slabs input {
  width: 100%;
  min-width: 0;
}

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

  .plan-side {
    position: static;
  }
}

/* On a phone the rail is a bar across the top: two links and signing out fit
   on a line or two, so nothing is folded away behind a menu. */
@media (max-width: 860px) {
  .console:has(> .console-rail) {
    display: block;
    padding: 0 16px 40px;
  }

  .console-nav.console-rail {
    position: static;
    min-height: 0;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    margin: 0 -16px;
    padding: 12px 16px;
  }

  .console-brand {
    padding: 0 8px 0 0;
  }

  .console-who {
    margin: 0 0 0 auto;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
  }
}

/* A one-time link is one unbroken string of about a hundred characters, and on
   a phone it would take the page sideways; it may break anywhere, because it is
   copied, never read. */
.console .note code {
  overflow-wrap: anywhere;
}

.console-nav,
.console-head form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

/* An agency's standing is changed by up to three controls in one cell. On a
   phone a stacked cell is a flex row beside its label, so the three stood side
   by side and took the list 166px past a 390px screen (the browser tier, 26
   September 2026). Here they wrap onto lines of their own under the label. */
@media (max-width: 760px) {
  .console td.standing {
    flex-wrap: wrap;
  }
}

/* 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;
}

/* --- The download page (`get_the_app.html`) -------------------------------- */
/*
   Read on a phone, by somebody who has no app yet and may not read English.
   Everything here has to hold at 390px, which is why the two downloads are a
   grid that becomes one column rather than a row that scrolls sideways -- the
   defect this project has measured on four separate pages.
*/
.lang-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 14px;
}
.lang-on,
.lang-off {
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 5px 11px;
  font-size: 0.86rem;
  line-height: 1.2;
  text-decoration: none;
}
.lang-on {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--white);
  font-weight: 600;
}
.lang-off {
  color: var(--ink);
  background: var(--white);
}
.lang-off:hover,
.lang-off:focus-visible {
  border-color: var(--navy);
}
.get-h {
  margin: 22px 0 8px;
  font-size: 1rem;
  font-weight: 700;
}
.get-grid {
  display: grid;
  /* One column until there is honestly room for two. 150px is the narrowest a
     card reads at with a two-line fleet name in Malayalam. */
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
}
.get-card {
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
}
.get-pick {
  border-color: var(--navy);
  box-shadow: 0 0 0 1px var(--navy) inset;
}
.get-fleet {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
}
.get-list {
  margin: 0;
  padding-left: 20px;
}
.get-list li {
  margin: 0 0 6px;
}
.get-sums {
  border-collapse: collapse;
  font-size: 0.78rem;
}
.get-sums th,
.get-sums td {
  text-align: left;
  vertical-align: top;
  padding: 4px 10px 4px 0;
  font-weight: 400;
}
/* A digest wraps rather than pushing the page sideways. 286px of overflow at 390
   wide is what `white-space: nowrap` here cost, measured by the browser tier --
   and a `.scroller` cannot save it, because the scroller sits in a flex column
   whose `min-width: auto` refuses to shrink below its content. Breaking is also
   the right answer for what this is for: the digest is read to be compared, not
   to be kept on one line, and selecting it still copies it whole. The same rule
   `.setup-card .token code` already uses for a set-up link. */
.get-sums td code,
.get-sums th {
  word-break: break-all;
}
.get-sums {
  width: 100%;
  table-layout: fixed;
}
.get-sums th {
  color: var(--muted);
}

/*
   The landing screen: choose a language, and nothing else to do.

   Large targets rather than the pills `.lang-row` uses once a language is
   chosen, because here the choice IS the screen and the reader has not been
   able to read anything yet. One per line at a phone width, so a name in any
   script has the whole width and none is harder to hit than another.
*/
.lang-ask {
  margin: 0 0 16px;
  padding: 0;
  list-style: none;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.5;
}
.lang-pick {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}
.lang-big {
  display: block;
  border: 1px solid var(--rule);
  border-radius: 10px;
  /* 52px tall at this padding and line height, which is the height every
     primary button in this product uses -- comfortably over the 44px floor. */
  padding: 15px 16px;
  font-size: 1.05rem;
  line-height: 1.4;
  font-weight: 600;
  color: var(--ink);
  background: var(--white);
  text-decoration: none;
}
.lang-big:hover,
.lang-big:focus-visible {
  border-color: var(--navy);
  background: var(--paper);
}
@media (min-width: 520px) {
  /* Two across once there is honestly room, which is the office's screen. */
  .lang-pick {
    grid-template-columns: 1fr 1fr;
  }
}

/* ---------- charts ----------
 * Bars across the page, drawn on the server (`api/charts.py`, `_charts.html`):
 * no script, no colour in the markup. **The words are HTML** at the page's own
 * type size, and only the bar beneath each is SVG -- a track stretched to the
 * row's width -- so a phone gets shorter bars and never smaller writing, and a
 * desk gets a chart that fills its card. Every colour is a token. */
.ch-figure {
  margin: 0;
}

.ch-row + .ch-row {
  margin-top: 10px;
}

.ch-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 13px;
}

.ch-name {
  min-width: 0;
  overflow-wrap: anywhere;
}

.ch-value {
  flex: none;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.ch-track {
  display: block;
  width: 100%;
  height: 14px;
  margin-top: 3px;
  background: var(--tint-2);
  border-radius: 3px;
}

.ch-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 4px;
}

.ch-grid {
  stroke: var(--tint-3);
  stroke-width: 1;
}

.ch-target {
  stroke: var(--red);
  stroke-width: 2;
  stroke-dasharray: 4 3;
}

/* The series, in the order a chart names them, and the two tones a target
 * gives: one class serves a segment in the track (fill) and its swatch in the
 * legend (background). */
.ch-s1 {
  fill: var(--navy);
  background: var(--navy);
}

.ch-s2 {
  fill: var(--blue);
  background: var(--blue);
}

.ch-s3 {
  fill: var(--amber);
  background: var(--amber);
}

.ch-s4 {
  fill: var(--green);
  background: var(--green);
}

.ch-s5 {
  fill: var(--muted);
  background: var(--muted);
}

.ch-under {
  fill: var(--red);
  background: var(--red);
}

.ch-over {
  fill: var(--green);
  background: var(--green);
}

.ch-keys {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 0 0 10px;
  padding: 0;
  list-style: none;
  font-size: 13px;
  color: var(--muted);
}

.ch-key {
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: 6px;
  border-radius: 2px;
}

.ch-note {
  margin-top: 4px;
}

.ch-table {
  margin-top: 10px;
}

.ch-table > summary {
  cursor: pointer;
  color: var(--blue);
  font-size: 13px;
  font-weight: 600;
}

.ch-table[open] > summary {
  margin-bottom: 6px;
}

/* Weekly charts standing up (`api/upright.py`): the drawing stretches to the
 * card, so a phone gets narrower weeks and the writing around it keeps its
 * size. The line keeps its width however the drawing is stretched. */
.ch-up {
  display: block;
  width: 100%;
  height: 160px;
  margin-top: 2px;
  background: var(--tint-1);
  border-radius: 3px;
}

.ch-line {
  fill: none;
  stroke: var(--blue);
  stroke-width: 2;
}

/* Two cards side by side at a desk, one above the other on a phone. */
.dash-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 16px;
}

/* The pair's gap spaces its two cards; the rule spacing cards that follow one
 * another would push the second down out of line with the first. */
.wrap .dash-pair > .card + .card {
  margin-top: 0;
}

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