/*
 * The partner portal's own styling, on the developer portal's tokens.
 *
 * ADR-0032 decision 5: the design is shared and the frame is not. The brand
 * tokens below are the ones `tools/portal/design.ts` defines, repeated here
 * rather than imported because that file exports one joined STYLE string whose
 * other halves are the reference and webhook pages, which this surface has no
 * use for.
 *
 * THAT SENTENCE WAS NOT TRUE and nothing was checking it. Of the ten token
 * names the two files share in each mode, eight differed in light and ten in
 * dark: a partner read this surface in `--ink` #1b1b1b and the documentation in
 * #14161a, on cards that were white here and warm there. ADR-0032 decision 5
 * names this as "the drift to watch" and says the defence "is not written".
 * It is written now, in `tools/checks/partner-controls.ts`, which compares
 * every shared name in both modes and fails on a difference. A token this
 * surface needs and the other has no use for is still its own; what the rule
 * refuses is two values under one name.
 *
 * The frame is a signed-in application: a rail down the left, a bar across the
 * top, cards in the middle. That is a different job from the reading portal,
 * which is a document people arrive at from a search engine. A body lives in
 * this one for years.
 */

/* ---------------------------------------------------------------- tokens */
:root {
  --brand: #d94a04;
  --brand-ink: #b03a03;
  --brand-wash: #fff4ed;
  --ink: #14161a;
  --ink-soft: #5b6472;
  --ink-faint: #8a8580;
  --bg: #ffffff;
  --surface: #faf8f6;
  --rail: #fbfaf9;
  --field: #fdfcfb;
  --line: #e7e4e0;
  --line-soft: #efedea;
  --good: #0a7d3f;
  --good-wash: #eaf6ef;
  --warn: #a06a06;
  --warn-wash: #fdf4e3;

  /* The sign-in panel, and the same in both themes on purpose: see the door. */
  --deep: #17120f;
  --deep-ink: #f7f3f0;
  --deep-soft: #c3b6ae;

  --r-sm: 6px;
  --r: 10px;
  --r-lg: 14px;
  --shadow: 0 1px 2px rgba(20, 22, 26, 0.06), 0 8px 24px rgba(20, 22, 26, 0.06);
  --shadow-lg: 0 4px 12px rgb(0 0 0 / 7%), 0 12px 32px rgb(0 0 0 / 7%);
  --rail-w: 252px;
}
:root[data-theme='dark'] {
  --brand: #ff7a2f;
  --brand-ink: #ff8244;
  --brand-wash: #241209;
  --ink: #edeef0;
  --ink-soft: #a1a8b3;
  --ink-faint: #7d7975;
  --bg: #0c0d0e;
  --surface: #141619;
  --rail: #181818;
  --field: #101215;
  --line: #262a30;
  --line-soft: #272727;
  --good: #4ec27f;
  --good-wash: #14291d;
  --warn: #e8b45c;
  --warn-wash: #2a2111;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.35);
  --shadow-lg: 0 8px 28px rgb(0 0 0 / 55%);
}

* {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font:
    15px/1.6 ui-sans-serif,
    system-ui,
    -apple-system,
    'Segoe UI',
    Roboto,
    sans-serif;
  -webkit-font-smoothing: antialiased;
}
h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.012em;
  line-height: 1.25;
}
h1 {
  font-size: 1.3rem;
}
h2 {
  font-size: 1.05rem;
}
h3 {
  font-size: 0.94rem;
}
p {
  margin: 0;
}
a {
  color: var(--brand-ink);
}
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}
.icon {
  flex: none;
  vertical-align: -0.18em;
}

/*
 * One focus ring, everywhere, in the brand colour.
 *
 * Only `.ctl` inputs had one, so every other focusable thing fell through to the
 * browser's own: the body selector drew Chrome's blue 1px rectangle inside a
 * rounded white card, which is the first thing on the page and looked like a
 * validation error. `:focus-visible` rather than `:focus`, so a mouse click does
 * not leave a ring behind, and the outline follows each element's own radius.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
/* Inside the rail's card there is no room for an offset ring. */
.whose select:focus-visible {
  outline-offset: 1px;
  border-radius: 4px;
}
/* A full-width row reads better with the ring tight against it. */
.line:focus-visible,
.stop:focus-visible,
.record:focus-visible,
.navlink:focus-visible {
  outline-offset: -2px;
}
.num {
  font-variant-numeric: tabular-nums;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ------------------------------------------------------------- the frame */
.app {
  display: grid;
  grid-template-columns: var(--rail-w) minmax(0, 1fr);
  min-height: 100vh;
}
.rail {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px 12px;
  background: var(--rail);
  border-right: 1px solid var(--line);
  overflow-y: auto;
}
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 2px 10px 16px;
  font-weight: 650;
  letter-spacing: -0.015em;
}
/* The mark is an SVG now and brings its own shape and colour; what is left
   here is only how it sits beside the word. */
.brand .mark-svg {
  flex: none;
}
.whose {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: none;
  padding: 6px 11px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow);
}
.whose .lbl {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.075em;
  color: var(--ink-faint);
  white-space: nowrap;
}
/* The names are long because they are the reader's own words, so the closed
   control ellipses rather than cutting one mid-word. */
.whose select {
  width: auto;
  max-width: 46vw;
  background: none;
  border: 0;
  padding: 0;
  font-size: 13px;
  font-weight: 550;
  cursor: pointer;
}
.rail .group {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.075em;
  color: var(--ink-faint);
  padding: 14px 12px 6px;
}
.navlink {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 11px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--ink-soft);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.navlink:hover {
  background: var(--field);
  color: var(--ink);
}
.navlink[aria-current='page'] {
  background: var(--brand-wash);
  color: var(--brand-ink);
  font-weight: 600;
}
.navlink .tally {
  margin-left: auto;
  min-width: 20px;
  padding: 1px 6px;
  border-radius: 99px;
  background: var(--field);
  color: var(--ink-soft);
  font-size: 11.5px;
  font-weight: 600;
  text-align: center;
}
.navlink[aria-current='page'] .tally {
  background: var(--brand);
  color: #fff;
}
/*
 * The page's own Save, at the foot of the rail.
 *
 * `.btn.rail-save` and not `.rail-save`, for the reason `.btn.rail-toggle`
 * above says: `.btn` sets its own background a hundred and fifty lines below
 * this at the same specificity, so source order decides it. Written the naive
 * way first, an hour after fixing the identical fault on the toggle, and
 * found by looking at the page: white text on the default surface, which is
 * a button nobody can read.
 *
 * It is here and not only in the Inspector because the rule-pack lines, Add
 * another and Remove all change the declaration from the page itself. Full
 * width, because it is the one verb on this surface that decides whether an
 * afternoon's work exists, and it sits below the sentence that says which of
 * the two states the page is in.
 */
.btn.rail-save {
  width: calc(100% - 24px);
  margin: 10px 12px 0;
  justify-content: center;
  border-color: var(--brand);
  background: var(--brand);
  color: #fff;
}
.btn.rail-save:hover {
  filter: brightness(1.06);
}

.rail .foot {
  margin-top: auto;
  padding: 14px 12px 0;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--ink-faint);
  border-top: 1px solid var(--line);
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 28px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.topbar .where {
  min-width: 0;
}
.topbar .where p {
  font-size: 12.5px;
  color: var(--ink-soft);
  margin-top: 1px;
}
.topbar .spacer {
  margin-left: auto;
}
main {
  padding: 26px 28px 96px;
  max-width: 1160px;
}
/*
 * `.btn.rail-toggle`, not `.rail-toggle`.
 *
 * Both toggles are `className="btn quiet rail-toggle"`, and `.btn` sets
 * `display: inline-flex` two hundred lines below this with the same
 * specificity, so source order decided it and the menu button was drawn at
 * every width on the partner surface from the day it was written. Found by
 * looking at the page at 1440px on 3 November, when the console was given
 * the same button; nothing in the suite or the checks can see a rule losing
 * to a later one.
 */
.btn.rail-toggle {
  display: none;
}

/* -------------------------------------------------------------- surfaces */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
}
.card > header {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line-soft);
}
.card > header .icon {
  color: var(--ink-faint);
}
.card > header .spacer {
  margin-left: auto;
}
/*
 * The search box that sits in a card's header.
 *
 * It takes a width of its own rather than `.ctl`'s full one, because it shares
 * a row with the heading and the count and would push both out of the card.
 */
.card > header input.find {
  width: min(260px, 44vw);
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  color: inherit;
  font: inherit;
}
.card > header input.find::placeholder {
  color: var(--ink-faint);
}
.card .body {
  padding: 16px 18px;
}
/*
 * A note between a card's header and its rows.
 *
 * It carries the card's own gutters, because `.lede` has none of its own and a
 * sentence that has to be read before the rows under it cannot sit flush
 * against the border. It was written as `lede thin` first, and `thin` was not
 * a class anywhere in this file.
 */
.card > .note {
  margin: 0;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line-soft);
  color: var(--ink-soft);
  font-size: 13.5px;
}
.card > .note b {
  color: var(--ink);
  font-weight: 600;
}
.card .body.flush {
  padding: 0;
}
.grid {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}
.lede {
  max-width: 68ch;
  color: var(--ink-soft);
  font-size: 14.5px;
}
.lede strong {
  color: var(--ink);
  font-weight: 600;
}
.section-head {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 30px 0 12px;
}
.section-head .icon {
  color: var(--ink-faint);
}
.section-head p {
  font-size: 13px;
  color: var(--ink-soft);
}

/* ----------------------------------------------------------------- bits */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: 99px;
  background: var(--field);
  color: var(--ink-soft);
  font-size: 11.5px;
  font-weight: 550;
  white-space: nowrap;
}
.pill.good {
  background: var(--good-wash);
  color: var(--good);
}
.pill.warn {
  background: var(--warn-wash);
  color: var(--warn);
}
.pill.brand {
  background: var(--brand-wash);
  color: var(--brand-ink);
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-size: 13px;
  font-weight: 550;
  cursor: pointer;
}
.btn:hover {
  background: var(--field);
}
.btn.primary {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.btn.primary:hover {
  background: var(--brand-ink);
}
.btn.quiet {
  border-color: transparent;
  background: none;
  color: var(--ink-soft);
}
.btn.quiet:hover {
  background: var(--field);
  color: var(--ink);
}
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 99px;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 12.5px;
  cursor: pointer;
}
.chip:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
}
.chip[aria-pressed='true'] {
  background: var(--brand-wash);
  border-color: var(--brand);
  color: var(--brand-ink);
  font-weight: 600;
}
.empty {
  display: grid;
  justify-items: center;
  gap: 8px;
  padding: 34px 20px;
  text-align: center;
  color: var(--ink-soft);
  font-size: 13.5px;
}
.empty .icon {
  color: var(--ink-faint);
}
.banner {
  display: flex;
  gap: 11px;
  padding: 13px 16px;
  border-radius: var(--r);
  background: var(--brand-wash);
  color: var(--brand-ink);
  font-size: 13.5px;
  line-height: 1.5;
}
.banner .icon {
  margin-top: 2px;
}
.banner.quiet {
  background: var(--field);
  color: var(--ink-soft);
}
/* Settled rather than outstanding. The brand wash above reads as something
 * to attend to, which is right for the unapproved half of this pair and
 * wrong for the half that says it is done. */
.banner.good {
  background: var(--good-wash);
  color: var(--good);
}

/* ---------------------------------------------------------- declaration */
.clause-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.clause-nav button {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: var(--ink-soft);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.clause-nav button:hover {
  background: var(--field);
  color: var(--ink);
}
.clause-nav button .n {
  margin-left: auto;
  font-size: 11px;
  color: var(--ink-faint);
}
.clause-nav button.vacant {
  opacity: 0.5;
}
.clause {
  margin-bottom: 18px;
  scroll-margin-top: 78px;
}
.clause > header .no {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--brand-wash);
  color: var(--brand-ink);
  font-size: 11px;
  font-weight: 700;
  flex: none;
}
.line {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  gap: 3px 12px;
  width: 100%;
  padding: 12px 18px;
  border: 0;
  border-top: 1px solid var(--line-soft);
  background: none;
  text-align: left;
  cursor: pointer;
}
.line:first-child {
  border-top: 0;
}
.line:hover {
  background: var(--field);
}
.line > .icon {
  grid-row: span 2;
  margin-top: 2px;
  color: var(--ink-faint);
}
.line .label {
  font-size: 14px;
  font-weight: 500;
}
.line .origin {
  grid-column: 2;
  font-size: 11.5px;
  color: var(--ink-faint);
}
.line .value {
  grid-row: span 2;
  align-self: center;
  max-width: 34ch;
  font-size: 13.5px;
  text-align: right;
  overflow-wrap: anywhere;
}
.line .value.vacant {
  color: var(--ink-faint);
  font-style: italic;
}
/*
 * "Still needed" on a line, which is required and unanswered.
 *
 * Not a colour alone: 89 of the 104 lines are required, so the ones left
 * are what a reader scans for and they have to be findable without
 * distinguishing two shades of grey. It sits in the third column beside
 * the value, where "not yet given" sits, because they answer the same
 * question from opposite ends.
 */
.line .needed {
  grid-column: 3;
  grid-row: 1;
  align-self: start;
  padding: 1px 8px;
  border: 1px solid var(--brand);
  border-radius: 999px;
  color: var(--brand-ink);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.line .cond {
  grid-column: 2 / -1;
  margin-top: 3px;
  font-size: 12px;
  color: var(--ink-soft);
}
.line .cond b {
  color: var(--brand-ink);
  font-weight: 600;
}
/*
 * Laid out like `.cond` beside it, which is to say not with flex. A flex child
 * in this grid's third column has no width to flow into, so every word of the
 * caveat took a line of its own. jsdom has no layout, so the tests were happy.
 */
.line .caveat {
  grid-column: 2 / -1;
  margin-top: 6px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--warn);
}
.line .caveat .icon {
  margin-right: 5px;
  vertical-align: -0.16em;
}
/*
 * What we hold on a line, wherever it is shown.
 *
 * All of this was scoped to `.line`, and the panel renders the same block: so
 * in the panel it lost the tint that marks it as ours, and `.held` lost the
 * flex row that separates "We hold" from the value. The words ran together.
 * A reader opening the line to look harder at a rate read "We hold2.5%", and
 * the two buttons under it read "That is rightThat is wrong", because `.acts`
 * lost its gap in the same way.
 *
 * Only the grid placement belongs to the line, because only the line is a grid.
 */
.ours {
  margin-top: 8px;
  padding: 11px 13px;
  border-radius: var(--r);
  background: var(--brand-wash);
  /*
   * Room above and below, for `ShownOnce` to scroll this card somewhere a
   * reader can actually read it.
   *
   * Below, because the button that copies the link is the card's sibling
   * rather than its child, so bringing the card in left the button a line
   * past the fold. Above, because `.topbar` is sticky at the top of the
   * scroller and 79px tall, measured in Chrome, so a card scrolled flush to
   * the top arrived underneath it with only its last line showing. A scroll
   * margin is what tells `nearest` this card is bigger than it looks.
   */
  scroll-margin-top: 96px;
  scroll-margin-bottom: 64px;
}
.line .ours {
  grid-column: 2 / -1;
}
/*
 * The rule pack's block, which used to be the last child of the line's own
 * <button>. A button's descendants are presentational, so the fieldset, the
 * two verbs, the select and the text box inside it were flattened out of the
 * accessibility tree. It sits beside the button now, on the same grid so the
 * indent is unchanged, and `.line[data-pack]` closes the gap underneath the
 * caption that the split would otherwise leave.
 */
.pack-held {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  gap: 3px 12px;
  padding: 0 18px 12px;
}
.pack-held > * {
  grid-column: 2 / -1;
}
.line[data-pack] {
  padding-bottom: 3px;
}
.ours.nothing {
  background: var(--field);
}
.ours .held {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  font-size: 13.5px;
}
.ours .held b {
  font-weight: 650;
}
.ours .cite {
  margin-top: 3px;
  font-size: 11.5px;
  color: var(--ink-soft);
}
.disagreed {
  margin-top: 8px;
}
.line .disagreed {
  grid-column: 2 / -1;
}
.disagreed .ctl {
  margin: 10px 0 0;
}
.ours .acts {
  display: flex;
  gap: 7px;
  margin-top: 10px;
}

/* ----------------------------------------------------------- repeats */
/*
 * A group of lines a body answers once for each of a thing: one set per plan,
 * one per account, one per former name. Set in from the clause's own lines so
 * the boundary of one of them is visible at a glance, which matters when there
 * are four plans of eight lines each.
 */
.repeats {
  border-top: 1px solid var(--line);
  background: var(--rail);
}
.repeats-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 18px 10px;
  font-size: 13px;
  color: var(--ink-soft);
}
.repeats-head .pill {
  margin-left: auto;
}
.instance {
  margin: 0 14px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.instance > header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--field);
}
.instance > header .icon {
  color: var(--brand);
}
.instance > header h3 {
  font-size: 13.5px;
}
.instance > header .spacer {
  margin-left: auto;
}
.instance > header .btn {
  padding: 3px 9px;
  font-size: 12px;
}
.instance .line {
  padding-inline: 14px;
}
.repeats-foot {
  padding: 2px 14px 16px;
}

/* ------------------------------------------------------------ inspector */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: rgb(0 0 0 / 28%);
  border: 0;
  padding: 0;
}
.inspector {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 21;
  width: min(440px, 100%);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-left: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
}
.inspector > header {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--line-soft);
}
.inspector > header .icon.lead {
  margin-top: 3px;
  color: var(--brand);
}
.inspector .meta {
  margin-top: 3px;
  font-size: 11.5px;
  color: var(--ink-faint);
}
.inspector .meaning {
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--ink-soft);
}
.note-small.good {
  color: var(--good);
}
/* The other half of the pair. `.good` was here alone and the one place that
 * wanted a warning tone on a small note reached for a class that did not
 * exist, so it rendered in the body colour and said nothing by its colour. */
.note-small.warn {
  color: var(--warn);
}

/*
 * The foot of the declaration's panel, where an answer says whether it is
 * kept. Outside `.scroll`, so it holds its place while a long line scrolls.
 */
.inspector > footer.keeping {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 20px;
  border-top: 1px solid var(--line-soft);
  background: var(--surface);
}
.inspector > footer.keeping .note-small {
  flex: 1;
  min-width: 0;
}
/* The verb last, against the edge the reader's hand is already at. */
.inspector > footer.keeping .btn {
  margin-left: auto;
  flex: none;
}
.inspector .scroll {
  flex: 1;
  overflow-y: auto;
  padding: 18px 20px 28px;
}
.facts {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 9px 14px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--line-soft);
  font-size: 13px;
}
.facts dt {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-soft);
  white-space: nowrap;
}
.facts dt .icon {
  color: var(--ink-faint);
}
.facts dd {
  margin: 0;
}

/* --------------------------------------------------------------- fields */
.ctl {
  display: block;
  margin-bottom: 13px;
}
.ctl > span {
  display: block;
  margin-bottom: 4px;
  font-size: 12.5px;
  color: var(--ink-soft);
}
.ctl input,
.ctl select,
.ctl textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
}
.ctl.inline {
  display: flex;
  align-items: center;
  gap: 9px;
}
.ctl.inline input {
  width: auto;
}
.drop {
  display: grid;
  justify-items: center;
  gap: 7px;
  padding: 22px;
  border: 1.5px dashed var(--line);
  border-radius: var(--r);
  background: var(--field);
  color: var(--ink-soft);
  font-size: 13px;
  text-align: center;
}
.drop:hover {
  border-color: var(--brand);
  color: var(--ink);
}
.chosen {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--field);
}
.chosen .icon {
  color: var(--brand);
}
.chosen .nm {
  font-size: 13.5px;
  overflow-wrap: anywhere;
}
.chosen .btn {
  margin-left: auto;
  flex: none;
}
.note-small {
  margin-top: 6px;
  font-size: 11.5px;
  color: var(--ink-faint);
}
.drop .icon {
  color: var(--ink-faint);
}

/* ------------------------------------------------------------- attempts */
.attempt {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 3px 13px;
  padding: 16px 18px;
  border-top: 1px solid var(--line-soft);
}
.attempt:first-child {
  border-top: 0;
}
.attempt .mark {
  grid-row: span 3;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
}
.attempt.can .mark {
  background: var(--good-wash);
  color: var(--good);
}
.attempt.cannot .mark {
  background: var(--brand-wash);
  color: var(--brand);
}
.attempt h3 {
  align-self: center;
}
.attempt .says {
  margin-top: 5px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-soft);
}
.attempt .says b {
  color: var(--ink);
  font-weight: 600;
}
.attempt .reads {
  margin-top: 9px;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
code,
.ref {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85em;
}
.ref {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 7px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--field);
  color: var(--ink-soft);
  cursor: pointer;
}
.ref:hover {
  border-color: var(--brand);
  color: var(--brand-ink);
}

/* ---------------------------------------------------------------- stops */
.stop {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px 18px;
  border: 0;
  border-top: 1px solid var(--line-soft);
  background: none;
  text-align: left;
  font-size: 13.5px;
  line-height: 1.55;
  cursor: pointer;
}
.stop:first-child {
  border-top: 0;
}
.stop:hover {
  background: var(--field);
}
.stop .depth {
  align-self: start;
  margin-top: 3px;
}
.stop .go {
  color: var(--ink-faint);
}

/* --------------------------------------------------------------- tables */
.table-wrap {
  overflow-x: auto;
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}
th,
td {
  padding: 10px 14px;
  text-align: left;
  vertical-align: top;
  border-top: 1px solid var(--line-soft);
}
thead th {
  border-top: 0;
  border-bottom: 1px solid var(--line);
  font-size: 10.5px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
  white-space: nowrap;
}
tbody tr:hover {
  background: var(--field);
}
td.r,
th.r {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
tr.total td {
  border-top: 2px solid var(--line);
  font-weight: 650;
}
tr.total:hover {
  background: none;
}
.guard {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--brand-ink);
}

/* -------------------------------------------------------------- the advice */
.advice {
  max-width: 780px;
}
.advice .rows {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
}
.advice .rows dt,
.advice .rows dd {
  margin: 0;
  padding: 9px 18px;
  border-top: 1px solid var(--line-soft);
  font-size: 13.5px;
}
.advice .rows dt {
  color: var(--ink-soft);
}
.advice .rows dd {
  text-align: right;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.advice .rows .group-head {
  grid-column: 1 / -1;
  padding: 14px 18px 5px;
  border-top: 1px solid var(--line);
  font-size: 10.5px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-faint);
}
.ack {
  border-color: var(--brand);
}
.ack > header {
  background: var(--brand-wash);
  color: var(--brand-ink);
  border-bottom-color: var(--brand);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.returned {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 7px 14px;
  margin-top: 14px;
  padding-top: 13px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
  color: var(--ink-soft);
}
.returned .v {
  text-align: right;
}

/* -------------------------------------------------------------- records */
.record {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 13px 18px;
  border: 0;
  border-top: 1px solid var(--line-soft);
  background: none;
  text-align: left;
  cursor: pointer;
}
.record:first-child {
  border-top: 0;
}
.record:hover {
  background: var(--field);
}
.record .avatar {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--brand-wash);
  color: var(--brand-ink);
  font-size: 12.5px;
  font-weight: 650;
  flex: none;
}
/*
 * A name over what it is, not beside it.
 *
 * `.nm` and `.sub` are spans with no display of their own, so they ran
 * together: "Adaeze OkonkwoDirector of Revenue" in People, "Account name for
 * this bodyBank" in Accounts, and "Adaeze Okonkwohmo-complete@example.ng" in
 * Who can sign in. The same fault `.held` was fixed for, which showed a reader
 * "We hold2.5%", in a different block that nothing was watching.
 */
.record .who {
  display: grid;
  min-width: 0;
}
.record .who .nm {
  font-size: 14px;
  font-weight: 500;
}
.record .who .sub {
  font-size: 12px;
  color: var(--ink-soft);
}
.record .spacer {
  margin-left: auto;
}
/*
 * Controls on a person's row, on a line of their own.
 *
 * `.record` is a flex row built for an avatar, two lines of text and one pill.
 * Two buttons on the end of it, inside a card that is one of three across,
 * left "Send again" and "Take it back" wrapping mid-phrase against the address
 * beside them. The row wraps instead and these take the width under it, which
 * is the same shape the panel uses for the controls under a line.
 */
.record {
  flex-wrap: wrap;
}
.record .row-acts {
  display: flex;
  flex-basis: 100%;
  gap: 6px;
  margin-left: 46px;
}

/* ------------------------------------------------------------ responsive */
@media (max-width: 760px) {
  /*
   * Hidden from the eye, not from the page. "You are a" is the whole of the
   * portal's explanation of the one control that decides what every other
   * surface is about, and `display: none` took it off the narrow layout most
   * readers open a link on, leaving a bare dropdown naming a body with nothing
   * saying whose it is or why it is there.
   */
  .whose .lbl {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .whose select {
    max-width: 52vw;
  }
}
@media (max-width: 1000px) {
  .app {
    grid-template-columns: 1fr;
  }
  .rail {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 30;
    width: var(--rail-w);
    transform: translateX(-100%);
    /*
     * `visibility`, and not `transform` alone, which is what this was.
     *
     * A transform moves pixels and nothing else: with the menu shut, every
     * navlink, the theme toggle and Sign out stayed in the tab order, so a
     * reader tabbing through the page watched focus disappear off the left
     * edge into eight controls they could not see. `visibility: hidden`
     * takes them out of it and still animates, because it is transitioned
     * alongside the transform rather than switched at the end.
     */
    visibility: hidden;
    transition:
      transform 0.18s ease,
      visibility 0.18s;
    box-shadow: var(--shadow-lg);
  }
  .rail[data-open='true'] {
    transform: none;
    visibility: visible;
  }
  .btn.rail-toggle {
    display: inline-flex;
  }
  .topbar,
  main {
    padding-inline: 16px;
  }
}
@media (max-width: 620px) {
  .inspector {
    top: auto;
    left: 0;
    width: 100%;
    height: 86vh;
    border-left: 0;
    border-top: 1px solid var(--line);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
  }
  .line {
    grid-template-columns: 22px minmax(0, 1fr);
  }
  .line .value {
    grid-row: auto;
    grid-column: 2;
    max-width: none;
    text-align: left;
  }
  .advice .rows {
    grid-template-columns: 1fr;
  }
  .advice .rows dt {
    padding-bottom: 0;
    border-top: 1px solid var(--line-soft);
  }
  .advice .rows dd {
    padding-top: 2px;
    border-top: 0;
    text-align: left;
  }
}
@media print {
  .rail,
  .topbar,
  .inspector,
  .scrim,
  .chips {
    display: none !important;
  }
  .app {
    grid-template-columns: 1fr;
  }
  .card {
    box-shadow: none;
    break-inside: avoid;
  }
}
@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
  }
}

/* A conditional line the page can tell applies, which is a thing being asked
   for and not a rule being explained. */
/*
 * A line the page can tell applies is a thing being asked for; one it can tell
 * does not apply should get out of the way. Both sentences sit in a `b`, and
 * `.cond b` paints that brand ink, so colouring the span alone changed nothing
 * on screen: the two verdicts looked the same in the browser while the markup
 * said they differed.
 */
.line .cond.wanted b {
  color: var(--warn);
  font-weight: 600;
}
.line .cond.settled b {
  color: var(--ink-soft);
  font-weight: 500;
}

/* ----------------------------------------------------------------- the gate */
/*
 * One form for both readers. Nothing on it says which kind you are, because
 * the credentials decide that and a choice here would be a way to guess.
 */
/* ----------------------------------------------------------------- the door

   Two panels: what this is, and the way in. The form keeps the `.gate` class
   it has always had, so it is still the thing every selector reaches for; what
   is new is the page it sits on.

   The left panel is the same deep tone in both themes. A sign-in page is the
   one screen a reader meets before the surface knows anything about them,
   including which colours they asked for, and a panel that changed underneath
   that moment would be the product fidgeting. */
.gate-page {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
}

.gate-brand {
  display: flex;
  flex-direction: column;
  gap: 40px;
  padding: 44px 48px;
  background: radial-gradient(120% 90% at 8% 4%, rgb(217 74 4 / 26%) 0%, transparent 58%),
    var(--deep);
  color: var(--deep-ink);
}
.gate-brand-top {
  display: flex;
  align-items: center;
  gap: 11px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.gate-brand-say {
  margin-top: auto;
  /* In pixels, not ch: `ch` here would be measured against this element's own
     16px and not against the heading's, which set the line far shorter than it
     looks and broke the sentence into four. */
  max-width: 460px;
}
.gate-name {
  margin: 0 0 10px;
  font-size: clamp(27px, 2.5vw, 36px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.028em;
}
.gate-who {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--deep-soft);
}

.gate-panel {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
}

.gate {
  width: 100%;
  max-width: 372px;
}
.gate h1 {
  margin: 0 0 7px;
  font-size: 27px;
  font-weight: 600;
  letter-spacing: -0.025em;
}
.gate .lede {
  margin: 0 0 26px;
  font-size: 13.5px;
}
.gate .ctl,
.gate .ctl-stack {
  margin-bottom: 15px;
}
.gate .ctl input {
  height: 44px;
}
.gate .btn.primary {
  width: 100%;
  height: 44px;
  justify-content: center;
  margin-top: 6px;
  font-size: 14px;
}
.gate .note-small {
  margin: 0 0 13px;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--warn);
  border-radius: 7px;
  background: var(--warn-wash);
  color: var(--ink);
}
.gate-foot {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line-soft);
  font-size: 12.5px;
  color: var(--ink-soft);
}
.gate-foot a {
  color: var(--brand-ink);
}

/* Seeing what was typed. Outside the label, because a label may not hold a
   second control, and the box keeps room for it so the two never overlap. */
.ctl-stack {
  position: relative;
}
.ctl-stack .ctl {
  margin-bottom: 0;
}
.ctl-stack .ctl input {
  padding-right: 62px;
}
.peek {
  position: absolute;
  right: 7px;
  bottom: 7px;
  height: 30px;
  padding: 0 10px;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--ink-soft);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.peek:hover {
  background: var(--field);
  color: var(--ink);
}

/* One column, and the panel becomes a strip. There is no room below the fold
   for what it says, and the form is what a reader came for. */
@media (max-width: 860px) {
  .gate-page {
    grid-template-columns: minmax(0, 1fr);
    /* The strip takes what it needs and the form takes the rest. Without this
       the two rows share the height evenly and the strip becomes a third of
       the screen, holding one mark. */
    grid-template-rows: auto minmax(0, 1fr);
    min-height: 100dvh;
  }
  .gate-brand {
    gap: 0;
    padding: 18px 22px;
  }
  .gate-brand-say {
    display: none;
  }
  .gate-panel {
    padding: 36px 22px 56px;
  }
}

/*
 * Who the reader is, stated rather than chosen. The record says it, so this is
 * a sentence and not a control: a body that could pick its own kind could pick
 * what it is asked and what it is paid against.
 */
.whose.said {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  padding: 7px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--rail);
  font-size: 13px;
}
.whose.said b {
  font-weight: 600;
}
.topbar .who {
  margin: 2px 0 0;
  font-size: 12.5px;
  color: var(--ink-soft);
}

/* Droomwork's own side of the same portal, which has no clause rail. */
.console-app .rail nav {
  padding: 8px 0;
}

/* The console's own few: a refusal it must not swallow, a row of buttons, and
   an invitation link, which is long and must wrap rather than run off. */
.console-app .refusal {
  margin: 0 0 16px;
  padding: 10px 13px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--warn);
  border-radius: 7px;
  background: var(--warn-wash);
  color: var(--ink);
  font-size: 13px;
}

/* A second line under a cell for a plain fact. `.guard` is brand-coloured and
   is for one worth catching the eye; the date a body last entered something is
   not that. */
.console-app .aside-line {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  font-weight: 400;
  color: var(--ink-faint);
}

.console-app .row-buttons {
  display: flex;
  gap: 9px;
  margin: 14px 0 0;
}

/*
 * NOT `.console-app .held b.long`, which is what this was.
 *
 * The same markup -- `.ours > .held > b.long` -- draws the invitation a
 * partner relays to a colleague, in `main.tsx`, and that surface is not
 * `.console-app`. So the one credential a partner has to pass on ran 183px
 * outside its card and was clipped, measured in Chrome on 29 October 2026,
 * while the console's identical card wrapped correctly. A rule scoped to one
 * of two surfaces that share a component is a rule that holds for one of them.
 */
.held b.long {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* ------------------------------------------------- the console's own panel */

/* The console's panel carries two tables, which 440px cannot hold without
   wrapping every cell. Same panel otherwise: same corner, same scrim, same
   header. */
.inspector.wide {
  width: min(560px, 100%);
}

.inspector .part {
  padding: 18px;
  border-top: 1px solid var(--line-soft);
}
.inspector .part:first-child {
  border-top: 0;
}
.inspector .part > h3 {
  margin: 0 0 13px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.inspector .part .table-wrap {
  margin: 0 -18px -18px;
}

/* ---------------------------------------------------------- the checkpoints

   Five things that happen to a body, in the order they happen, each with its
   own mark. Reached is the green the dry run gives an attempt that works, the
   one being waited on is the brand colour it gives one that does not, and
   everything after is an outline: it has not happened, and colouring it would
   say it nearly has. */
.track {
  list-style: none;
  margin: 0;
  padding: 0;
}
.track li {
  position: relative;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  column-gap: 13px;
  padding-bottom: 17px;
}
.track li:last-child {
  padding-bottom: 0;
}
/* the rail joining one mark to the next, drawn behind them */
.track li::before {
  content: '';
  position: absolute;
  left: 13px;
  top: 30px;
  bottom: 0;
  width: 2px;
  background: var(--line);
}
.track li:last-child::before {
  display: none;
}
.track li.done::before {
  background: var(--good);
  opacity: 0.4;
}
.track .mark {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 9px;
  background: var(--field);
  color: var(--ink-faint);
}
.track li.done .mark {
  background: var(--good-wash);
  color: var(--good);
}
.track li.now .mark {
  background: var(--brand-wash);
  color: var(--brand);
}
.track b {
  align-self: center;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}
.track li.later b {
  font-weight: 500;
  color: var(--ink-faint);
}
.track .when {
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ink-faint);
}

/* The same five small enough for a row of the list. It says nothing a reader
   cannot get from the line beside it, so it is hidden from anyone not reading
   by eye rather than read out as five words with no meaning. */
.railmarks {
  display: inline-flex;
  align-items: center;
}
.railmarks span {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--line);
}
.railmarks span + span {
  position: relative;
  margin-left: 17px;
}
.railmarks span + span::before {
  content: '';
  position: absolute;
  right: 8px;
  top: 50%;
  width: 17px;
  height: 2px;
  transform: translateY(-50%);
  background: var(--line);
}
.railmarks span.done {
  background: var(--good);
}
.railmarks span.done + span::before {
  background: var(--good);
  opacity: 0.45;
}
.railmarks span.now {
  background: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-wash);
}

/* ------------------------------------------------------- opening the panel

   The scrim fades and the panel comes in from the edge it is pinned to. Both
   are entry animations only: `both` holds the end state, so nothing here can
   leave the panel part-way if a frame is dropped.

   A reader who has asked their machine for less movement gets the same panel
   with none of it. The animation is not shortened to something still visible:
   the request is for no motion, so there is none. */
@keyframes scrim-arrives {
  from {
    opacity: 0;
  }
}
@keyframes panel-arrives {
  from {
    opacity: 0;
    transform: translateX(100%);
  }
}
.scrim {
  animation: scrim-arrives 170ms ease-out both;
}
.inspector {
  animation: panel-arrives 260ms cubic-bezier(0.22, 0.75, 0.3, 1) both;
}
@media (prefers-reduced-motion: reduce) {
  .scrim,
  .inspector {
    animation: none;
  }
}

/* ------------------------------------------- the controls at the rail's foot

   `.rail .foot` is pushed to the bottom and carries the divider above it. A
   body's portal has two of them -- the controls, then the sentence about what
   becomes of what they type -- and the second must not draw the line again or
   push itself down a second time. */
.rail .foot + .btn.rail-save {
  margin-top: 10px;
}
.rail .foot + .foot {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
/*
 * Who is signed in, at the foot of the rail above the two controls it is about.
 *
 * Its own block rather than borrowing `.foot.tools`, which is a flex row built
 * for buttons and would lay the name and the address side by side. The address
 * uses `.guard`, which is already the small grey second line used under a
 * field id in the console, so the two read the same way.
 */
.foot.whoami {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding-bottom: 2px;
  color: var(--ink-soft);
  font-size: 12.5px;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.foot.whoami b {
  display: block;
  color: var(--ink);
  font-weight: 600;
}
.foot.whoami .icon {
  flex: none;
  margin-top: 1px;
}

.foot.tools {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  padding-bottom: 10px;
}
.btn.theme {
  gap: 8px;
  font-size: 12.5px;
  color: var(--ink-soft);
}
.btn.theme .icon {
  flex: none;
}

/* ------------------------------------------------------------- the way back

   Above the title rather than beside it, so it reads as where a reader came
   from and not as part of the name of where they are. Quiet, because it is a
   way out of somewhere and never the thing to do on the page. */
.where .back {
  margin: 0 0 2px -7px;
  padding: 3px 7px;
  gap: 5px;
  font-size: 12px;
  color: var(--ink-soft);
}
.where .back .icon {
  flex: none;
}

/* ------------------------------------------------------- what has happened */
/*
 * The log a body reads of its own account. ADR-0035.
 *
 * Tokens only, like everything above: ADR-0032 decision 5 makes
 * `tools/portal/design.ts` the one source for both surfaces and
 * `check:partner-controls` compares the two palettes, so a colour written out
 * here would be a colour that drifts.
 */
.log-note {
  margin: 0;
  font-size: 13.5px;
  color: var(--ink-soft);
}
/*
 * What an entry was about, under the sentence and not beside it.
 *
 * A span with no display of its own, which is the fault `.record .who` and
 * `.held` were both fixed for: "Read your declarationAbout Adaeze Okonkwo."
 * run together in one cell. `check:partner-controls` holds this selector by
 * name now, so it cannot lose the property again without the build saying so.
 */
.log-about {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  color: var(--ink-soft);
}
.log-unknown {
  color: var(--warn);
}
.log-missing {
  margin: 9px 0 0;
  padding-left: 18px;
  font-size: 13px;
  color: var(--ink-soft);
}
.log-missing li + li {
  margin-top: 5px;
}

/*
 * The form that stops one of a body's people. ADR-0035 decision 13.
 *
 * It replaced a `window.prompt`, which could collect one string and so
 * collected the one the body never reads. Two fields and two buttons on a
 * person's row, so it takes the width under them the way `.record .row-acts`
 * does.
 */
.stop-form {
  display: grid;
  gap: 8px;
  /*
   * `flex-basis` was here, for `.record`, the flex row a body's own colleague
   * card uses. The console's people are a table, where it does nothing: the
   * form rendered 85 pixels wide inside a right aligned cell, with every label
   * wrapped to one word a line and the chooser cut off at "Choose". It has a
   * row of its own across all three columns now, so the width comes from the
   * table and this sets only the stacking.
   */
  max-width: 34rem;
  margin: 2px 0 6px;
  text-align: left;
}
.stop-form .ctl {
  display: grid;
  gap: 3px;
}

/*
 * A relationship that has ended, said on every page. ADR-0037.
 *
 * Above the page's own content rather than inside it, because it is true of
 * all eight and a reader who lands on their declaration should know before
 * they start typing.
 */
.ended {
  margin: 0 0 18px;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--warn);
  border-radius: var(--r);
  background: var(--warn-wash);
  color: var(--ink);
  font-size: 13.5px;
  line-height: 1.55;
}

/*
 * A line of context under a card header, inside the padded part.
 *
 * `.log-note` sets the voice; `.pad` gives it the card's own padding when it
 * sits above a `.body flush` that has none of its own.
 */
.log-note.pad {
  padding: 10px 18px 0;
}

/*
 * A line that cannot be answered any more. ADR-0037.
 *
 * A `<fieldset disabled>` around a control, which disables every form element
 * inside it including ones a later type adds. `display: contents` takes the
 * fieldset itself out of the layout, so it changes what the controls do and
 * nothing about where they sit, and the browser default border, margin and
 * padding go with it.
 */
.frozen {
  display: contents;
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

/*
 * And what one looks like, which the fieldset does not decide.
 *
 * `disabled` stops the typing and changes nothing on screen: measured in
 * Chrome, a text box inside that fieldset still draws its answer in full ink
 * on the field background inside a live border, at opacity 1, with the
 * ordinary cursor. It is pixel for pixel a box that takes an answer, and it
 * silently swallows the click. That is the page saying one thing in the banner
 * and doing another under the pointer, and it is the whole fault the prop was
 * added to prevent -- so the prop alone would not have prevented it.
 *
 * A frozen box therefore stops being a box. The border and the field
 * background go and the padding closes up, leaving the answer as written text.
 *
 * THE INK STAYS AT FULL STRENGTH, which is the part to keep. Reading what they
 * entered is the whole of what a closed body may still do, and the usual way
 * to draw a dead control -- fade it -- would take that away to make a point
 * they have already been told in the banner. `-webkit-text-fill-color` is set
 * with it because that, and not `color`, is what greys disabled text out in
 * this engine.
 *
 * The hint goes. A placeholder is a sample of what to type here, and on an
 * account nobody can type into it invites something the page will refuse.
 *
 * Checkboxes and radios are left alone: they carry the answer in the box
 * itself, so a transparent background would erase it rather than quiet it.
 */
.frozen input:not([type='checkbox']):not([type='radio']),
.frozen select,
.frozen textarea {
  border-color: transparent;
  background: transparent;
  padding-left: 0;
  padding-right: 0;
  cursor: default;
  color: var(--ink);
  -webkit-text-fill-color: var(--ink);
  opacity: 1;
}
.frozen input::placeholder,
.frozen textarea::placeholder {
  color: transparent;
}
/*
 * The presses that stay. Every press this surface offers a closed body is taken
 * away rather than greyed -- add, remove, "Change this", "That is right",
 * "Choose another", "This does not apply to us" -- because each is a verb and a
 * greyed verb still states an offer. The exception is the chip row of an `Enum
 * list`, where the pressed chips are the answer and the rest are the list it
 * was chosen from, so they are greyed instead. `controls.tsx` carries that
 * argument.
 *
 * NOTHING ON THE PAGE MATCHES THIS TODAY, which is worth knowing before
 * deleting it. `T1-001` is the only `Enum list` field any of the six bodies is
 * asked, and it is also an `EXAMPLE_PACK` line -- the inspector draws the pack
 * for those and no control at all -- so the chip branch is unreachable. Walking
 * all forty four lines of a closed body in Chrome found no press inside a
 * frozen fieldset. The rule is kept because the day a second `Enum list` line
 * is added it is wanted immediately, and because a chip that looks pressable
 * and is not is the fault the rule above this one exists to stop.
 */
.frozen button {
  cursor: default;
  border-style: dashed;
  color: var(--ink-faint);
}

/* ---------------------------------------------------------------- totals
 *
 * The band of figures over the payments table. A grid rather than a flex row
 * so the figures line up on their own baseline whatever their width, and
 * `auto-fit` so two of them do not sit at opposite ends of a wide window.
 */
/*
 * FLEX AND NOT `grid-template-columns: repeat(auto-fit, ...)`, which was here
 * first and left half the band empty.
 *
 * `auto-fit` collapses a track only while nothing occupies it, and the caveat
 * below spans `1 / -1`, so it occupies every track there is. With two figures
 * on screen -- which is the ordinary case, since the piles with nothing in
 * them are not drawn -- the two sat squeezed at the left under three columns
 * of nothing. Found by opening the page; the markup and the tests were both
 * perfectly happy.
 */
.totals {
  margin-top: 18px;
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  background: var(--line-soft);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.totals .figure {
  display: flex;
  flex: 1 1 190px;
  flex-direction: column;
  gap: 3px;
  padding: 15px 18px;
  background: var(--surface);
}
.totals .figure .what {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.totals .figure strong {
  font-size: 22px;
  font-weight: 650;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
.totals .figure.lead strong {
  font-size: 27px;
  color: var(--brand-ink);
}
.totals .figure strong.warn {
  color: var(--warn);
}
.totals .figure .when {
  font-size: 12px;
  color: var(--ink-soft);
}
/*
 * The caveat spans the whole band and sits under it, because a figure read on
 * its own is exactly how this page once told a body it had been paid.
 */
.totals .made-up {
  /* Its own line, the whole width of the band. */
  flex: 1 0 100%;
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 11px 18px;
  background: var(--warn-wash);
  color: var(--warn);
  font-size: 12.5px;
}
.totals .made-up .icon {
  flex: none;
  margin-top: 1px;
}
.totals.invented .figure strong {
  /* Invented figures do not get the confident colour. */
  color: var(--ink-soft);
}
