/* ==========================================================================
   Poruch — design system.

   Distilled from BCC (Spectre.css 0.6 with a dark toolbar and a per-state
   colour band). Spectre itself is not vendored: it is abandoned SCSS, 131 KB
   compiled, and nine tenths of it is grid and components we do not use. What
   is kept is every decision that makes BCC readable — the palette, the 12.8px
   dense scale, the .3em radius, the sticky head with a diagonal state slash,
   the table with group dividers and a state edge, and the right-hand column
   that is filters on a list and audit on a record.

   Every value lives in a custom property, so a theme is a token block, not a
   fork. Section 1 is byte-identical to `../mockups/css/mockup.css`'s, on
   purpose: it is the contract with the drawn screens, and a drift in one token
   is a drift on every page.

   Five things this file decides differently from the mockups it came from.
   They are decisions, not omissions, and each is argued where it applies:

   1. The current navigation item is matched by BOTH `.is-current` and
      `[aria-current="page"]`. The attribute is the accessible answer, the
      class is the visual one, and a helper that has to emit both is a helper
      that can emit one and not the other. Sections 3, 4 and 18.

   2. There is NO classless baseline. `simple.css` dressed fourteen bare tags
      — 27 `<dl>`, 14 `<table>`, 11 `<fieldset>`, every `<p>label<br>input</p>`
      form row — and this file styles about fourteen tags and expects a class
      everywhere else. A baseline for the un-ported screens would be a second
      design system that only they could see, and it would have to be deleted
      again. So `<dl>`/`<dt>`/`<dd>` have no rule at all: section 12's
      `.fields` is what a record read back is.

   3. Dark mode is DROPPED, and it is a real loss. `simple.css` and
      `panel.css` both shipped a `prefers-color-scheme: dark` palette, and
      `panel.css`'s was a deliberate correction rather than an inheritance.
      A dark theme here is a second `:root` under a media query and nothing
      else — but the work is picking nineteen `--state-*` pairs, and the state
      edge carries meaning (a state colour that reads wrong is a lie, not a
      blemish). A partial dark palette over nineteen states is worse than
      none. If it comes back, it comes back as its own pass against the token
      block, with the mockups extended first.

   4. Print support is TWO RULES and that is a named regression. Section 25
      carries them forward. Everything this file introduces is print-hostile:
      `.toolbar` is a dark ground that will not adjust, `.page-head` /
      `.table thead th` / `.audit-day` / `.surface-side .panel-head` are all
      sticky, `.surface-side` and `.board` clip, and the state edges carry
      meaning that a colour-stripped print loses entirely. A printable card,
      record read-back or audit trail is net-new work and was not attempted.

   5. The eleven stage hues are a PALETTE, not eleven seed slugs. The mockups
      hard-coded `.state-due_diligence` and ten siblings because they were
      drawn against one fund's demo data; `Stage` had no colour, so a second
      company's board rendered grey and a renamed stage lost its hue. Section
      11's palette is `.state-hue-1` … `.state-hue-11`, in the same order and
      the same colours, so the demo fund still renders exactly as drawn.

      Which one a stage wears is an attribute on `Stage`, chosen when the stage
      is made, and it stores the palette KEY rather than a colour. That is the
      part worth defending: every hue here is a PAIR — a line and a pale wash —
      picked by hand against this light ground, and deriving a readable wash
      from an arbitrary hex is not something this file attempts. The palette is
      closed, and it is eleven.

      Two stages may share a hue. A unique constraint would put a ceiling on
      the board at the twelfth stage, which is a worse thing than two columns
      the same colour.

      The four workflow-lifecycle states and the four run/claim states keep
      their names, because those are closed enums in the model rather than
      tenant data.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Surfaces. --bg is the page, --surface is anything raised off it. */
  --bg: #f4f4fb;
  --bg-sunken: #ececf5;
  --surface: #ffffff;
  --surface-head: #dcdcf0;

  /* Ink */
  --fg: #455060;
  --fg-strong: #303742;
  --fg-muted: #7c8797;
  --fg-faint: #a8b0bd;

  /* Lines */
  --line: #bcc3ce;
  --line-soft: #d4d8e0;
  --line-strong: #9fa9b9;

  /* Primary — Spectre's indigo, unchanged. It is the only accent. */
  --primary: #4f4fbb;
  --primary-hover: #4343ad;
  --primary-line: #4646b5;
  --primary-wash: #eeeefa;

  /* The toolbar. Near-black navy: the chrome must not compete with the work. */
  --chrome: #001a33;
  --chrome-hover: #002b54;
  --chrome-active: #00355e;
  --chrome-fg: #c1c1c1;
  --chrome-fg-strong: #f0f0f0;

  /* Signals */
  --ok: #2f9e41;
  --ok-wash: #e6f5e9;
  --warn: #b07800;
  --warn-wash: #fdf3dd;
  --bad: #c2410c;
  --bad-wash: #fbeae1;

  /* Keys and code — monospace on a warm wash, so an identifier never reads
     as prose. */
  --code-fg: #d73e48;
  --code-bg: #fcf2f2;

  --highlight: #ffe9b3;

  /* Type. 0.8rem of a 16px root = 12.8px. Dense on purpose: these screens are
     read as tables of facts, not as articles. */
  --font: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", sans-serif;
  --mono: "SF Mono", "Segoe UI Mono", "Roboto Mono", Menlo, Courier, monospace;
  --fs: 0.8rem;
  --fs-sm: 0.7rem;
  --fs-lg: 0.9rem;
  --fs-h1: 0.9rem;
  --fs-h2: 1.15rem;
  --fs-h3: 0.95rem;
  --lh: 1.2rem;

  /* Space. One .26rem step, doubled and tripled — Spectre's unit scale. */
  --u1: 0.26rem;
  --u2: 0.52rem;
  --u3: 0.78rem;
  --u4: 1.04rem;
  --u5: 1.3rem;
  --u6: 1.56rem;
  --u8: 2.08rem;
  --u10: 2.6rem;

  --radius: 0.3em;
  --hair: 0.05rem;

  --shadow: 0 0.1rem 0.3rem rgba(48, 55, 66, 0.14);
  --shadow-head: 0 0.1rem 0.2rem rgba(48, 55, 66, 0.16);

  /* The panel head sticks to the top of the right-hand column, and the day
     separator of a timeline stands just under it. One number, used twice. */
  --panel-head-h: 2.3rem;

  --side-width: 22rem;
  /* Written twice on purpose: a custom property cannot appear in a media
     condition, so section 6's `@media (max-width: 1120px)` carries the
     literal. The token is not dead — it is the name of the number. */
  --side-collapse: 1120px;

  /* The page head is sticky and two things stick underneath it, so its height
     is a declared number rather than three guesses that drift apart. The head
     is given it as a `height` — a min-height would be a floor and not a
     promise, and the two things stick at the number whatever the head does.

     2.4rem is 38.4px, and the tallest thing the row can hold is 36.83px: a
     page tab, which is the 1.2rem line plus the 0.52rem padding pair, and a
     `code` crumb, which is that line plus 1px of its own border. The remaining
     1.57px is the slack, and it is why everything in the row below is held to
     one line.

     It was 4rem while the head was two stacked rows — a trail over a title —
     and shrinking it is most of what merging them bought: 25.6px of chrome
     back on every screen, and a whole second row of chrome back on the
     seventy-nine that also carried a band. */
  --head-h: 2.4rem;
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: 16px;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: var(--fs);
  line-height: var(--lh);
  text-rendering: optimizeLegibility;
}

a {
  color: var(--primary);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  color: var(--fg-strong);
  font-weight: 600;
  line-height: 1.3;
}

h2 {
  font-size: var(--fs-h2);
}

h3 {
  font-size: var(--fs-h3);
}

p {
  margin: 0 0 var(--u2);
}

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

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

hr {
  border: 0;
  border-top: var(--hair) solid var(--line-soft);
  margin: var(--u4) 0;
}

code,
.key {
  padding: 0.1rem var(--u1);
  border-radius: var(--radius);
  background: var(--code-bg);
  color: var(--code-fg);
  font-family: var(--mono);
  font-size: 85%;
  white-space: nowrap;
}

/* A whole command, or a whole file. `code` above is an identifier inside a
   sentence and refuses to break; this is the thing itself, so it keeps its own
   line breaks and wraps rather than scrolling — the longest line here is a URL
   with a company subdomain in it, and a horizontal scrollbar under a command
   somebody is about to copy hides half of what they are copying.

   `overflow-wrap: anywhere` and not `break-word`, for the reason the grid
   traps in DESIGN_SYSTEM.md give: only `anywhere` lowers the min-content size
   the column is measured against. */
.snippet {
  margin: 0;
  padding: var(--u3);
  border: var(--hair) solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--code-bg);
  color: var(--fg-strong);
  font-family: var(--mono);
  font-size: 85%;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  tab-size: 2;
}

/* <pre><code> is the markup a command deserves, and the chip styling above has
   to come off the inner element or the block wears two grounds. */
.snippet code {
  padding: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font-size: 100%;
  white-space: inherit;
}

/* A numbered path through somebody else's window. The list reset above kills
   the marker on every list in the app, which is right — every other list here
   is a row of records — and wrong for the one place where the number IS the
   instruction: "second, paste the address". */
.steps {
  list-style: decimal;
  padding-left: var(--u5);
}

.steps > li + li {
  margin-top: var(--u2);
}

time {
  font-variant-numeric: tabular-nums;
}

.num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

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

.faint {
  color: var(--fg-faint);
}

.small {
  font-size: var(--fs-sm);
}

.strong {
  color: var(--fg-strong);
  font-weight: 600;
}

/* A label with something more to say, said on hover. The words are the
   browser's own `title` tooltip rather than a component of this file, and the
   reason is `overflow`: a tooltip drawn with `::after` is clipped by the
   scrolling right column and by a wide table's `.table-wrap`, while the
   browser draws its own outside the page box entirely.

   What `title` cannot do is reach a keyboard or a touch, so NOTHING A READER
   MUST HAVE GOES IN ONE. The dotted underline is the whole of the affordance:
   without it a hover-only hint is a hint nobody knows to look for. */
.note {
  text-decoration: underline dotted var(--line-strong);
  text-underline-offset: var(--u1);
  cursor: help;
}

.right {
  text-align: right;
}

.nowrap {
  white-space: nowrap;
}

mark {
  background: var(--highlight);
  color: inherit;
}

/* A value as it moved. Used in the audit column and in any builder row that
   has to say what a draft changes — one vocabulary, so a reader learns it
   once. */
ins,
del {
  padding: 0 var(--u1);
  border-radius: var(--radius);
}

ins {
  background: var(--ok-wash);
  color: #1d6b2b;
  text-decoration: none;
}

del {
  background: var(--bad-wash);
  color: #92320a;
}

del + ins,
ins + del {
  margin-left: var(--u1);
}

/* --------------------------------------------------------------------------
   3. Toolbar — the sections of the tenant
   -------------------------------------------------------------------------- */

.toolbar {
  display: flex;
  align-items: stretch;
  gap: var(--u1);
  padding: 0 var(--u2);
  background: var(--chrome);
}

.toolbar .brand {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  margin-right: var(--u2);
  font-size: var(--fs-h1);
  font-weight: 600;
}

.toolbar .brand a {
  display: flex;
  align-items: center;
  gap: var(--u2);
  padding: var(--u2) var(--u2);
  border-radius: var(--radius);
  color: var(--chrome-fg-strong);
}

.toolbar .brand a:hover {
  background: var(--chrome-hover);
  text-decoration: none;
}

/* The mark stands for the company so the way home is a thing, not a word. */
.toolbar .brand .mark {
  display: grid;
  place-items: center;
  width: 1.35rem;
  height: 1.35rem;
  border-radius: var(--radius);
  background: var(--primary);
  color: #fff;
  font-size: var(--fs-sm);
  font-weight: 700;
}

.toolbar .sections {
  display: flex;
  align-items: stretch;
  flex: 1 1 auto;
  gap: var(--u1);
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.toolbar .sections::-webkit-scrollbar {
  display: none;
}

.toolbar .sections a {
  display: flex;
  align-items: center;
  padding: 0 var(--u3);
  color: var(--chrome-fg);
  white-space: nowrap;
}

.toolbar .sections a:hover {
  background: var(--chrome-hover);
  color: var(--chrome-fg-strong);
  text-decoration: none;
}

.toolbar .sections a.is-current,
.toolbar .sections a[aria-current="page"] {
  background: var(--chrome-active);
  color: #fff;
  box-shadow: inset 0 -0.15rem 0 var(--primary);
}

/* The account menu is a <details> and nothing else — a menu that needed a
   controller would put a script on every page for one control. */
.toolbar .account {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
}

/* The avatar is what you see; the summary is what you hit. They are two
   elements because a 1.5rem circle is a fine thing to look at and a poor
   thing to aim at — the target is the full height of the toolbar and the
   padding around the disc, exactly like a section tab beside it. */
.toolbar .account > summary {
  display: flex;
  align-items: center;
  padding: 0 var(--u2);
  cursor: pointer;
  list-style: none;
}

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

.toolbar .account > summary:hover {
  background: var(--chrome-hover);
}

.toolbar .account > summary .avatar {
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: #24384e;
  color: var(--chrome-fg-strong);
  font-size: var(--fs-sm);
  font-weight: 600;
}

.toolbar .account[open] > summary {
  background: var(--chrome-active);
}

.toolbar .account[open] > summary .avatar {
  background: var(--primary);
}

/* THE WAY OUT IS THE WAY IN. The menu had no dismissal but a second press on
   the avatar, so a click on the page left it hanging open over what you were
   reading. The remedy is the one the off-canvas drawer below already uses,
   in its own words: the scrim belongs to the open state, so a click anywhere
   outside is a click on the control that opened it. There that control is a
   link and the scrim is an `<a href="#close">`; here it is the summary, so
   the scrim is the summary's own ::before and the native toggle does the
   closing. No element to add, no script to load, and nothing that can be
   left behind — it exists only while `[open]` does.

   IT IS INVISIBLE AND THE DRAWER'S IS NOT. That one dims at .35 because it
   is a 26rem panel over the whole page of a phone, and the dim is what says
   the page is still behind it. This hangs off its own trigger and covers
   four lines of nothing. Dimming for it would make the account menu heavier
   than a destructive confirmation, which asks for a press and gets no scrim
   at all.

   It carries no background, rather than a black one at zero opacity: a
   transparent box is a hit target already, and the colour nobody sees is an
   invitation to the next reader to turn it up "just to check it works".

   Between the sticky band (30) and the menu itself (40), because the band is
   the one thing on the page that would otherwise stay pressable underneath.

   AND IT DOES NOT POINT, which has to be written rather than left out:
   `cursor` inherits, the summary above is a `pointer`, so this box was given
   one without anybody asking for it — a pointing hand over the whole viewport,
   over paragraphs and table rows that do nothing. That is a claim about what
   is under the cursor and the claim is false; the press here dismisses, and
   nobody goes hunting for a dismissal. `default` and not `auto`, because the
   scrim takes the press: an I-beam over text that can no longer be selected is
   the same lie in a smaller size. The drawer's scrim keeps its own pointer and
   is right to — it is a real link, and its .35 dim makes the overlay the thing
   the cursor is standing on. */
.toolbar .account[open] > summary::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 35;
  cursor: default;
}

.toolbar .account > ul {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 40;
  min-width: 15rem;
  margin-top: var(--u1);
  padding: var(--u1);
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}

/* The padding lives on the row's own child, not on the li: a menu entry that
   only answers on its words is a target the width of the word. Where the
   child is a link it fills the row, so the whole row is the link. */
.toolbar .account > ul li {
  padding: 0;
}

.toolbar .account > ul li > a,
.toolbar .account > ul li > span {
  display: block;
  padding: var(--u1) var(--u2);
  border-radius: var(--radius);
  color: var(--fg);
}

.toolbar .account > ul li > a:hover {
  background: var(--bg-sunken);
  color: var(--fg-strong);
  text-decoration: none;
}

.toolbar .account > ul li + li {
  border-top: var(--hair) solid var(--line-soft);
}

.toolbar .account small {
  display: block;
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   4. Head — where you are, what else is here, and what you can do about it

   One row under the toolbar, and the only one. It used to be two: a band of
   the subject's pages, and a page head under it carrying a crumb trail and
   the page's name in large type. On a record that wrote the name twice within
   sixty-four pixels of itself, and on a list it put "Administration / Agents"
   in 11px grey directly above "Agents" in 18px black. Counted: of the
   eighty-one screens that have both, twenty-six repeat the last crumb in the
   title word for word.

   So the two are one row with two costumes, and which one a page wears is
   decided by a question about the page rather than by taste:

     * a subject WITH PAGES OF ITS OWN wears the collapsed trail — a way out,
       the subject, and its pages:
       `← All agents | Startup Research Agent | Overview Executions History`.
       The trail is not missing, it is folded into the arrow: everything above
       this record is one place, and the arrow is the click to it.

     * everything else wears the TRAIL:
       `Administration / Forms / Startup Investment Application / Rename`.
       The last crumb is the page, and it is written in the ink of a heading
       because it is now the only thing on the screen that names it.

   White rather than the band's sunken ground. The sunken ground was for chrome
   standing above the page; this row is the page's own name. What separates it
   from the work is the shadow, and since the row is sticky the shadow does
   that job on every scroll rather than as decoration.
   -------------------------------------------------------------------------- */

.page-head {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: stretch;
  gap: var(--u4);
  height: var(--head-h);
  padding: 0 var(--u5);
  background: var(--surface);
  box-shadow: var(--shadow-head);
}

/* Centred on the row, all of it — except the pages, which are stretched. The
   mark on the current one is a bottom border and it has to land on the row's
   own bottom edge; centred, it draws a line through the middle of the head. */
.page-head > * {
  align-self: center;
}

/* The way out, and the whole of the trail above this record. One link, because
   a record reached from a list has one place above it — the list. */
.page-head .page-back {
  padding-right: var(--u4);
  border-right: var(--hair) solid var(--line);
  color: var(--primary);
}

.page-head .page-back::before {
  margin-right: var(--u1);
  content: "\2190";
}

/* The record's own name, and the one thing in this row that may be long
   enough to need cutting. It shrinks and the pages beside it do not: a tab is
   a fixed label two words wide, and a name is whatever somebody typed. */
.page-head .page-subject {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  padding-right: var(--u4);
  border-right: var(--hair) solid var(--line);
  color: var(--fg-strong);
  font-size: var(--fs);
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Takes the slack, so the chips and the actions sit at the right edge. */
.page-head .page-pages {
  display: flex;
  align-self: stretch;
  flex: 1 1 auto;
  gap: var(--u4);
}

.page-head .page-pages a {
  display: flex;
  align-items: center;
  border-bottom: 0.15rem solid transparent;
  color: var(--fg-muted);
}

.page-head .page-pages a:hover {
  color: var(--fg-strong);
  text-decoration: none;
}

.page-head .page-pages a.is-current,
.page-head .page-pages a[aria-current="page"] {
  border-bottom-color: var(--primary);
  color: var(--fg-strong);
  font-weight: 600;
}

.page-head .page-actions {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  gap: var(--u2);
}

/* --------------------------------------------------------------------------
   5. Surface — the two columns under the head
   -------------------------------------------------------------------------- */

.surface {
  display: block;
}

/* One line, always, and the reason is the row it sits in: `.page-head` is
   given --head-h as a HEIGHT, and both `.table thead th { top: var(--head-h) }`
   and `.surface-side { top: calc(var(--head-h) + var(--u2)) }` stick at that
   number and cannot see what the head actually did. A trail that wrapped would
   put the whole column-header row behind the head, and nobody sees that until
   they scroll. */
.crumbs {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
  gap: var(--u2);
  color: var(--fg-muted);
  font-size: var(--fs);
}

/* The last crumb is the page. Nothing else on the screen says which page this
   is now, so it is written in the ink a heading would have been written in —
   and it is never a link, because it leads where the reader already stands. */
.crumbs li:last-child {
  color: var(--fg-strong);
  font-weight: 600;
}

/* A crumb is one place, so it is never broken across lines. It is ellipsed
   from the end instead: the separator its ::before draws sits at the start of
   the box and survives, so the trail still reads as a trail.

   The cap is what makes that true, and leaving it to flexbox does not. Shrink
   is distributed in proportion to basis, so every crumb loses the same
   PERCENTAGE — measured, a 200-character name in a four-crumb trail at 960px
   took `Forms` from 45px to 17.92px, which is one glyph and an ellipsis, while
   the name that caused it kept 432px. The trail stopped being a trail and
   became a long name with punctuation in front of it.

   11.5rem is 184px, and the widest name in the seeded tenant — "Startup
   Investment Application", thirty characters — is 176.31px. So the cap clears
   every real name with 7.7px to spare and only bites something genuinely long.

   Two other rules were measured and are worse. 9rem protects the short crumbs
   on 13 of 15 deep-trail cases against this one's 11, and cuts every name in
   the demo tenant at every width to buy it — including "Startup Application
   Review" at 1400px with six hundred pixels of empty head beside it. A share of
   the row (33%) sounds like it should scale with the room and does not: the
   crumb row is stretched to the head's full width whether the trail needs it
   or not, so a third of a mostly-empty narrow row is a small absolute
   number, and three long crumbs at a third each overflow before the short ones
   and the gaps get anything. It scored 6 of 15 and broke the six-crumb trail at
   1400 as well, which no length does.

   The ceiling: two deep-trail cases still collapse — the six-crumb validation
   trails below 1120px, which carry three user-supplied names in one row. No cap
   of any width fixes those; fitting them needs about fourteen characters, which
   cuts "Vendor onboarding" itself. The upgrade path is not a tighter cap but
   `flex-shrink: 0` on the crumbs that are fixed labels and `1` on the ones that
   are record names — CSS is trying to infer from length what the call site
   already knows, and telling it directly would cut only when the trail truly
   does not fit and never touch "Administration" or "Forms". That is a change to
   how every screen writes its crumbs, so it is not this rule's to make. */
.crumbs li {
  min-width: 0;
  max-width: 11.5rem;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.crumbs li + li::before {
  margin-right: var(--u2);
  content: "/";
  color: var(--fg-faint);
}

.crumbs .count {
  color: var(--fg-faint);
}

/* A SCOPE IS A CRUMB THAT SWITCHES. How a collection is being read used to be
   a `.page-tabs` row inside the page, and once the scope became the last crumb
   the page said it twice — the trail said Archived and a row eight pixels
   below offered Archived pressed. So the crumb is the control: it names the
   reading and opens the others, with the counts the tab row used to carry.

   The trade is a row of the page for a press, and it is worth it only while
   the menu holds EVERY scope with its count. Tabs show four readings without
   being asked; a menu that showed three would buy the row with the reader not
   learning that Archived exists.

   Same machinery as the account menu, in its own words there: a `<details>`,
   a scrim that is the summary's own ::before, and no script — so it opens,
   closes on a press anywhere and closes on a second Enter without one.

   Four rules below exist only to keep the trail out of its own menu: the
   entries are `<li>`s inside `.crumbs`, so the separator, the ellipsis cap,
   the strong ink of the last crumb and the overflow that does the cutting all
   reach in unless they are turned off. */
/* Flex, because `<details>` is a block: left alone it took the whole line and
   dropped itself under the separator its own ::before had just drawn. */
.crumbs li:has(> .scope) {
  display: flex;
  align-items: center;
  max-width: none;
  overflow: visible;
}

.scope {
  position: relative;
}

.scope > summary {
  display: flex;
  align-items: center;
  gap: var(--u1);
  color: var(--fg-strong);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}

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

.scope > summary::after {
  content: "\25BE";
  color: var(--fg-faint);
  font-weight: 400;
}

.scope[open] > summary::after {
  color: var(--fg-muted);
}

.scope[open] > summary::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 35;
  cursor: default;
}

.scope > ul {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 40;
  min-width: 11rem;
  margin-top: var(--u1);
  padding: var(--u1);
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}

/* `.crumbs` is in the selector for the weight alone, and it has to be: the
   trail's own `.crumbs li:last-child` is a class, a pseudo-class and a type,
   which outranks `.scope > ul li` and reached the LAST entry of the open menu.
   Every board read Live and printed Closed in the same strong ink, so the menu
   named two readings as the one you were on. */
.crumbs .scope > ul li,
.scope > ul li {
  max-width: none;
  overflow: visible;
  font-weight: 400;
}

.crumbs .scope > ul li + li::before {
  content: none;
  margin-right: 0;
}

.scope > ul li > a {
  display: flex;
  justify-content: space-between;
  gap: var(--u5);
  padding: var(--u1) var(--u2);
  border-radius: var(--radius);
  color: var(--fg);
}

.scope > ul li > a:hover {
  background: var(--bg-sunken);
  color: var(--fg-strong);
  text-decoration: none;
}

.scope > ul li > a[aria-current="page"] {
  color: var(--fg-strong);
  font-weight: 600;
}

/* A page wearing the COLLAPSED costume has no trail to put the scope in, so it
   stands beside the pages instead — same control, same words, one place along.
   It takes the slack from the pages when it is there, so the chips and the
   actions stay at the right edge either way. */
.page-head > .scope {
  margin-right: auto;
}

.page-head .page-pages:has(+ .scope) {
  flex: 0 0 auto;
}

.surface-body {
  display: flex;
  align-items: flex-start;
  flex-wrap: nowrap;
  gap: var(--u5);
  padding: var(--u4) var(--u5) var(--u10);
}

.surface-main {
  flex: 1 1 auto;
  min-width: 0;
}


.surface-side {
  flex: 0 0 var(--side-width);
  position: sticky;
  top: calc(var(--head-h) + var(--u2));
  max-height: calc(100vh - var(--head-h) - var(--u4));
  overflow-y: auto;
}

/* Whatever the main column stacks — a section, a notice, the stage rail —
   is separated by one step. Written against any sibling rather than against
   `section + section`, which left a notice welded to the panel under it. */
.surface-main > * + * {
  margin-top: var(--u5);
}

/* And whatever the right column stacks, one step smaller because the column
   is. A record with two things to say about it — an access panel above a
   history, both halves of a member's audit, a filter panel above a saved view
   — puts two panels there, and without this they weld into one box with two
   heads. The mockups wrote the number inline on every side column that has a
   second panel, which makes it a missing modifier rather than a per-screen
   decision. */
.surface-side > * + * {
  margin-top: var(--u3);
}

/* --------------------------------------------------------------------------
   6. Off-canvas — the right column under a narrow viewport.

   Pure CSS: `#sidebar` opens, `#close` shuts, and the scrim belongs to the
   open state, so a click anywhere outside is a click on the control that
   opened it.
   -------------------------------------------------------------------------- */

a.side-toggle,
.side-close,
a.side-scrim {
  display: none;
}

@media (max-width: 1120px) {
  a.side-toggle {
    display: inline-flex;
  }

  .surface-side {
    display: none;
  }

  .surface-side:target {
    display: block;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 60;
    width: min(26rem, 100%);
    max-height: none;
    padding: var(--u3);
    background: var(--bg);
    box-shadow: -0.2rem 0 0.6rem rgba(48, 55, 66, 0.2);
    overflow-y: auto;
  }

  .surface-side:target .side-close {
    display: flex;
    justify-content: flex-end;
    margin-bottom: var(--u2);
  }

  .surface-side:target ~ a.side-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 50;
    background: rgba(48, 55, 66, 0.35);
  }
}

/* --------------------------------------------------------------------------
   7. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--u1);
  padding: var(--u2) var(--u3);
  border: var(--hair) solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--primary);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--fs);
  line-height: var(--lh);
  text-align: center;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  white-space: nowrap;
}

.btn:hover {
  border-color: var(--primary);
  background: var(--primary-wash);
  text-decoration: none;
}

.btn-primary {
  border-color: var(--primary-line);
  background: var(--primary);
  color: #fff;
}

.btn-primary:hover {
  border-color: var(--primary-hover);
  background: var(--primary-hover);
  color: #fff;
}

.btn-danger {
  border-color: var(--bad);
  color: var(--bad);
}

.btn-danger:hover {
  background: var(--bad-wash);
  border-color: var(--bad);
}

/* A destructive button that has been armed and will fire on the next press —
   `arming_controller.js` puts the class on, the popup takes it off again. The
   outline fills in, which is the one place in this file a button is flooded
   with a signal colour: the resting state of every destructive control is an
   outline, so filling one is a state and not a style.

   The hover is declared identically rather than left out, because the rule
   above would otherwise wash the armed button back out from under the
   pointer that is about to press it. */
.btn-danger.is-armed,
.btn-danger.is-armed:hover {
  border-color: var(--bad);
  background: var(--bad);
  color: #fff;
}

.btn-link {
  border-color: transparent;
  background: transparent;
}

.btn-link:hover {
  border-color: transparent;
  background: rgba(79, 79, 187, 0.08);
}

.btn-sm {
  padding: var(--u1) var(--u2);
  font-size: var(--fs-sm);
}

.btn[disabled],
.btn.is-disabled {
  border-color: var(--line);
  background: var(--bg-sunken);
  color: var(--fg-faint);
  cursor: not-allowed;
  pointer-events: none;
}

.btn-group {
  display: inline-flex;
}

.btn-group .btn {
  border-radius: 0;
  margin-left: calc(-1 * var(--hair));
}

/* The radii belong to the ENDS OF THE GROUP, not to a button's position inside
   its own wrapper: with the wrapper present every button is both the first and
   the last child of something, and each one would draw a full pill. */
.btn-group > .btn:first-child,
.btn-group > :first-child .btn {
  border-radius: var(--radius) 0 0 var(--radius);
  margin-left: 0;
}

.btn-group > .btn:last-child,
.btn-group > :last-child .btn {
  border-radius: 0 var(--radius) var(--radius) 0;
}

/* A control that mutates is a <form>. Rails' `button_to` wraps its button in
   one and `form_with` wraps everything it lays out, and a <form> is a block
   box — so a row of controls that includes one would stack instead of lining
   up. Every place the design system lays controls out in a row takes the
   wrapper out of the layout, and the control inside it becomes the flex item.
   Stated once here rather than five times, because it is one fact about Rails
   and not five decisions.

   Two consequences worth knowing. `display: contents` removes the box and
   nothing else: the form still submits. And a structural selector still counts
   the wrapper as the parent, which is why `.btn-group`'s corner radii are
   written against the group's own ends below. */
.btn-group > form,
.panel-foot > form,
.form-inline > form,
.form-actions > form,
.page-actions > form {
  display: contents;
}

/* --------------------------------------------------------------------------
   8. Chips — an enum, a count, a state
   -------------------------------------------------------------------------- */

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--u1);
  padding: 0.1rem var(--u2);
  border-radius: var(--radius);
  background: var(--bg-sunken);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  line-height: 1.1rem;
  white-space: nowrap;
}

.chip-strong {
  background: var(--primary-wash);
  color: var(--primary);
}

.chip-ok {
  background: var(--ok-wash);
  color: var(--ok);
}

.chip-warn {
  background: var(--warn-wash);
  color: var(--warn);
}

.chip-bad {
  background: var(--bad-wash);
  color: var(--bad);
}

.chip-agent::before {
  content: "\2699";
  color: var(--fg-faint);
}

.chip-count {
  font-family: var(--mono);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--u1);
}

/* --------------------------------------------------------------------------
   9. Panels
   -------------------------------------------------------------------------- */

.panel {
  display: flex;
  flex-direction: column;
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.panel-head {
  display: flex;
  align-items: center;
  gap: var(--u2);
  padding: var(--u2) var(--u3);
  border-bottom: var(--hair) solid var(--line-soft);
  color: var(--fg-strong);
  font-weight: 600;
}

.panel-head .spacer {
  flex: 1 1 auto;
}

.panel-body {
  padding: var(--u3);
}

.panel-body-flush {
  padding: 0;
}

/* What belongs to the panel rather than to the page: an add-strip, a sentence
   about the table above it, the two buttons that publish what the panel shows.
   A row, because that is what every foot the mockups draw is — and a row with
   a spacer in it, because the sentence in a foot sits at the far end from the
   button it is about. */
.panel-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--u2);
  padding: var(--u2) var(--u3);
  border-top: var(--hair) solid var(--line-soft);
  background: var(--bg);
}

.panel-foot .spacer {
  flex: 1 1 auto;
}

/* A panel that offers its Save only once there is something to save.
   `app/javascript/controllers/dirty_controller.js` puts the class on and takes
   it off, and NOTHING ELSE DOES: with no JavaScript the class never appears
   and the foot is simply always there, which is the form this panel has always
   been. */
.panel.is-unchanged > .panel-foot {
  display: none;
}


.surface-side .panel-head {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface);
}

/* A panel holding a form, capped at a width somebody can read a line back
   from. On the panel rather than on the column, because a page is rarely only
   a form: an editor puts the form beside a table of permissions or of options,
   and that table wants every pixel the page has.

   The actions strip takes the cap too, and has to be named separately because
   it is the panel's SIBLING rather than its foot — which is itself a decision,
   argued at `.form-actions`. Without this it inherits nothing and its rule runs
   154px past the panel it closes, which is a hairline pointing at nothing. A
   strip after an uncapped `.panel` still matches its panel, because this
   selector does not reach it. */
.panel-form,
.panel-form + .form-actions {
  max-width: 52rem;
}

/* First in a panel body there is nothing above it to split from: the panel
   head's own rule is the line, and a second one 30px under it with a word
   floating in the gap is two rules where the reader expected one. */
.panel-body > .divider:first-child {
  margin-top: 0;
  border-top: 0;
}

.panel-body > .divider:first-child[data-content]::after {
  top: 0;
}

/* A titled rule, for splitting a column of filters into named groups. */
.divider {
  position: relative;
  display: block;
  margin: var(--u4) 0 var(--u2);
  border-top: var(--hair) solid var(--line-soft);
  text-align: center;
}

.divider[data-content]::after {
  position: relative;
  top: -0.6rem;
  display: inline-block;
  padding: 0 var(--u2);
  background: var(--bg);
  color: var(--fg-faint);
  content: attr(data-content);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* --------------------------------------------------------------------------
   10. Tables

   The list is the product. Group dividers separate what a reader compares
   from what a reader only glances at, the head sticks under the page head,
   and a row that has a state wears it as a right-hand edge.
   -------------------------------------------------------------------------- */

/* The frame around a table, and nothing else. It must not establish a scroll
   container: `position: sticky` resolves its offset against the nearest
   scrollport, so an `overflow` here — even one that never actually overflows —
   pins the head `--head-h` down inside the table instead of under the page
   head.
   A table too wide for its column widens the page, which is what BCC does and
   what the sticky head is there for. */
.table-wrap {
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

/* The opt-out, for a table that must not widen the page. It scrolls itself,
   and its head therefore cannot stick — that is the trade, not a bug. */
.table-scroll {
  overflow-x: auto;
}

.table-scroll .table thead th {
  position: static;
}

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

.table th,
.table td {
  padding: var(--u2) var(--u2);
  border-bottom: var(--hair) solid var(--line-soft);
  text-align: left;
  vertical-align: top;
}

.table thead th {
  position: sticky;
  top: var(--head-h);
  z-index: 20;
  border-bottom: 0.1rem solid var(--line);
  background: var(--surface);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.table thead th a {
  color: inherit;
}

.table thead th a::after {
  content: " \2195";
  color: var(--fg-faint);
}

.table thead th.is-sorted a {
  color: var(--fg-strong);
}

.table thead th.is-sorted a::after {
  content: " \2193";
  color: var(--primary);
}

.table tbody tr:last-child th,
.table tbody tr:last-child td {
  border-bottom: 0;
}

.table-striped tbody tr:nth-child(even) {
  background: rgba(236, 236, 245, 0.5);
}

.table-hover tbody tr:hover {
  background: var(--primary-wash);
}

/* A row that leads somewhere. The whole row is the target; the link inside is
   what a keyboard reaches. */
.table tbody tr[data-href] {
  cursor: pointer;
}

/* .right is declared with the base utilities, and `.table td` is declared
   here — later, same specificity — so a right-aligned cell needs saying twice.
   Numbers that do not line up are the one table defect a reader notices every
   single time. */
.table th.right,
.table td.right {
  text-align: right;
}

.table .group {
  border-left: var(--hair) solid var(--line);
}

.table td ul > li {
  padding: 0.1rem 0;
}

.table .cell-title {
  color: var(--fg-strong);
  font-weight: 600;
}

.table caption {
  padding: var(--u2);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  text-align: left;
}

/* --------------------------------------------------------------------------
   11. States

   One hue per stage. A row carries it as a 5px right edge, a chip as a pale
   wash, and the page head as a diagonal slash across its left third — which
   is the single detail that tells you at a glance where a card stands.
   -------------------------------------------------------------------------- */

.state {
  --state: var(--fg-muted);
  --state-wash: var(--bg-sunken);
}

/* An inset shadow on the last cell rather than a border on the row. Under
   `border-collapse: collapse` a row's right border is painted in the collapsed
   border area, which sits OUTSIDE the table's `width: 100%` — the row came out
   4px wider than the table and squared off the wrap's rounded corner. A shadow
   takes part in no layout at all. */
tr.state > :last-child {
  box-shadow: inset -0.25rem 0 0 var(--state);
}

.chip.state {
  background: var(--state-wash);
  color: var(--state);
}

/* The slash runs into --surface and not --surface-head: the head is white
   since the trail moved into it, and a gradient ending in the old lavender
   painted a second, invisible band across the right two thirds of the row. */
.page-head.state {
  background: linear-gradient(
    107deg,
    var(--state-wash) 0,
    var(--state-wash) 13.5em,
    var(--surface) 13.6em,
    var(--surface) 100%
  );
}

.dot {
  display: inline-block;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--state);
}

/* Workflow lifecycle */
.state-draft {
  --state: #7b8391;
  --state-wash: #e9ebee;
}
.state-active {
  --state: #2f9e41;
  --state-wash: #e3f3e6;
}
.state-paused {
  --state: #b07800;
  --state-wash: #f8eed6;
}
.state-archived {
  --state: #7b4fc0;
  --state-wash: #eee8f8;
}

/* The stage palette. Eleven pairs, in the order the demo fund's process runs
   its stages, which is the order they were drawn in.

   The mockups keyed these on eleven seed slugs (`.state-due_diligence`, …)
   because they were drawn against one fund. Which one a stage wears is an
   attribute on `Stage` now, and the attribute holds the KEY — never a colour.
   Each entry is a line and a wash chosen together against this ground; a wash
   derived from an arbitrary hex is not a thing this file will guess at. So the
   palette is closed at eleven, a stage made without a choice falls back to its
   position in the process, and two stages may share a hue — a unique
   constraint would cap the board at twelve columns, which is worse than two
   columns the same colour. */
.state-hue-1 {
  --state: #0184a5;
  --state-wash: #dcedf2;
}
.state-hue-2 {
  --state: #0064a7;
  --state-wash: #dbe6f2;
}
.state-hue-3 {
  --state: #009aa5;
  --state-wash: #daf0f1;
}
.state-hue-4 {
  --state: #5e7400;
  --state-wash: #e9eed6;
}
.state-hue-5 {
  --state: #c07401;
  --state-wash: #f8ead6;
}
.state-hue-6 {
  --state: #00a77d;
  --state-wash: #d9f1eb;
}
.state-hue-7 {
  --state: #5a2ea6;
  --state-wash: #e7e0f4;
}
.state-hue-8 {
  --state: #b32a23;
  --state-wash: #f6e0de;
}
.state-hue-9 {
  --state: #088f03;
  --state-wash: #daeeda;
}
.state-hue-10 {
  --state: #aa2702;
  --state-wash: #f4e0da;
}
.state-hue-11 {
  --state: #7f7f7f;
  --state-wash: #e8e8e8;
}

/* Run and claim states, for the queue */
.state-waiting {
  --state: #0064a7;
  --state-wash: #dbe6f2;
}
.state-held {
  --state: #c07401;
  --state-wash: #f8ead6;
}
.state-committed {
  --state: #2f9e41;
  --state-wash: #e3f3e6;
}
.state-lost {
  --state: #b32a23;
  --state-wash: #f6e0de;
}

/* --------------------------------------------------------------------------
   12. Field lists — a record read back
   -------------------------------------------------------------------------- */

/* The value track is `minmax(0, 1fr)` and not `1fr`, and the difference is the
   whole rule. A bare `1fr` is `minmax(auto, 1fr)`, so its floor is the
   content's min-content width — one unbreakable `https://harborfreightdata…`
   sets that floor and the grid grows past the column it is in. In the right
   column, which is a scrollport, the text is then silently clipped rather than
   pushing the page: it was found by reading a seeded card whose domain name
   happened to be four characters longer than the one beside it. */
.fields {
  display: grid;
  grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr);
  gap: 0;
  margin: 0;
}

.fields dt {
  padding: var(--u2) var(--u3) var(--u2) 0;
  border-top: var(--hair) solid var(--line-soft);
  color: var(--fg-muted);
}

.fields dd {
  margin: 0;
  padding: var(--u2) 0;
  border-top: var(--hair) solid var(--line-soft);
  color: var(--fg-strong);
}

/* `anywhere` rather than `break-word`, because only `anywhere` also lowers the
   min-content size the track above is measured against. A URL is the case that
   matters and it has no break opportunity in it at all. */
.fields dt,
.fields dd {
  overflow-wrap: anywhere;
}

.fields dt:first-of-type,
.fields dt:first-of-type + dd {
  border-top: 0;
}

/* The rule above clears the first PAIR, and a two-column list puts two pairs
   in its first row. The second kept its border and drew a hairline across the
   right half of the top of the list, starting exactly where a label begins —
   ten screens, and it went unseen until a row grew tall enough to separate the
   line from the label it was crossing. `nth-of-type(2)` is exact because this
   list is strict dt/dd alternation. */
.fields-2 dt:nth-of-type(2),
.fields-2 dt:nth-of-type(2) + dd {
  border-top: 0;
}

.fields dd.is-hidden {
  color: var(--fg-faint);
  font-style: italic;
}

/* A value committed with a problem says so under itself. The problem is a
   fact about the card, not about the empty row, so it takes none of
   `.is-hidden`'s italics. */
.fields dd .form-error {
  font-style: normal;
}

/* Two columns of fields, for a record wide enough to earn them. */
.fields-2 {
  grid-template-columns: minmax(8rem, 11rem) minmax(0, 1fr) minmax(8rem, 11rem) minmax(0, 1fr);
}

/* One column, the label a caption over its value — for the 22rem side, where
   two tracks do not fit. A label and a 64-character digest cannot share the
   nineteen rems a panel leaves inside that column, and the two-track grid
   answers an unbreakable value by shrinking the label track until the label
   itself breaks: `Applied` came out one letter per line. Stacked, both get the
   whole width and neither has to give.

   The separator moves to the dt with the row it opens; a dd's border would
   draw a line between a label and its own value. */
.fields-stacked {
  grid-template-columns: minmax(0, 1fr);
}

.fields-stacked dt {
  padding: var(--u2) 0 0;
  font-size: var(--fs-sm);
}

.fields-stacked dd {
  padding: 0 0 var(--u2);
  border-top: 0;
}

/* --------------------------------------------------------------------------
   13. Forms
   -------------------------------------------------------------------------- */

.form-group {
  margin-bottom: var(--u3);
}

.form-group:last-child {
  margin-bottom: 0;
}

.form-label {
  display: block;
  margin-bottom: var(--u1);
  color: var(--fg-strong);
  font-weight: 600;
}

.form-label .req {
  color: var(--bad);
}

.form-hint {
  margin-top: var(--u1);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

.form-input,
.form-select,
textarea.form-input {
  display: block;
  width: 100%;
  padding: var(--u2) var(--u2);
  border: var(--hair) solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--fg-strong);
  font-family: inherit;
  font-size: var(--fs);
  line-height: var(--lh);
}

.form-input:focus,
.form-select:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 0.1rem rgba(79, 79, 187, 0.2);
  outline: none;
}

textarea.form-input {
  min-height: 4.5rem;
  resize: vertical;
}

.form-input[readonly] {
  background: var(--bg-sunken);
  color: var(--fg-muted);
}

/* A box or a radio and the words that explain it, as one target. The label is
   the row, so the browser gives the whole row to the click without a script —
   and the hover says so, because a control that answers a press anywhere has
   to look like one. A radio is a five-pixel target standing beside sixty
   characters of the sentence a reader is actually pointing at. */
.form-check {
  display: flex;
  align-items: center;
  gap: var(--u2);
  padding: var(--u1) 0;
  cursor: pointer;
}

.form-check:hover {
  background: var(--primary-wash);
}

/* A choice that carries a sentence explaining it. The control aligns to the
   first line rather than to the middle of three, and the name is held to a
   column so several of them read as a list instead of as paragraphs that
   happen to start with a dot. */
.form-check-described {
  align-items: flex-start;
  padding: var(--u2) var(--u1);
}

.form-check-described > input {
  margin-top: 0.2rem;
}

.form-check-name {
  flex: none;
  width: 11rem;
  font-weight: 600;
}

/* Several out of a short closed list, drawn as tags rather than as a
   `<select multiple>`. The native control shows four rows of however many
   there are and marks a chosen one with a grey band indistinguishable from
   focus; here what is chosen is filled in and everything is on screen at once.

   The checkbox itself is taken out of the flow rather than hidden: `display:
   none` and `visibility: hidden` both take it out of the tab order, and the
   only reason this control works without a line of script is that it is still
   a checkbox. Its state is read with `:has` on the label that wraps it. */
.picker {
  display: flex;
  flex-wrap: wrap;
  gap: var(--u1);
}

.picker-tag {
  position: relative;
  padding: 0.1rem var(--u2);
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  line-height: 1.1rem;
  white-space: nowrap;
  cursor: pointer;
}

.picker-tag input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.picker-tag:hover {
  border-color: var(--primary);
  color: var(--primary);
}

.picker-tag:has(:checked) {
  border-color: var(--primary);
  background: var(--primary-wash);
  color: var(--primary);
  font-weight: 600;
}

/* The focus ring belongs to the tag, because the box it would otherwise draw
   around is one pixel wide and off in the corner. */
.picker-tag:has(:focus-visible) {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

/* A SCOPE THAT IS A FILTER RATHER THAN A PLACE. The head's scope menu is a
   place: one reading at a time, and it stands in the trail because it says
   where you are. Some lifecycles are not that — a reader who wants the
   archived records BESIDE the live ones is filtering, and a menu of one
   choice cannot say it. So the halves are toggles, both can be on, and "All"
   is not an entry because it is both of them.

   THEY ARE BUTTONS THAT STAY DOWN, and the whole design is in that sentence.
   Up is `.btn` — same padding, same border, same ground — and down is the same
   button with the light coming from the other side: a step darker, a stronger
   line, and the outer shadow that lifts a control replaced by an inset one,
   because that is the edge a pressed thing sinks under. No tick, no box.

   GREY AND NOT INDIGO, which is the one colour decision here. Indigo is the
   product's single accent and it means an action — press this and something
   happens. These change what a list shows and nothing else, so they are the
   ink of the pager's own buttons beside them. A filled indigo toggle also put
   a second primary in the panel, against the Apply button two sections down.

   The checkbox is moved off the screen rather than hidden, so it keeps the
   keyboard and the label keeps the click, and the ring is put back on the
   button it controls — `display: none` would take Tab away with it. */
/* A row of them is a control like any other in the panel, so it leaves the
   same gap under it as a `.form-group` does. It had none, and it took removing
   the LIFECYCLE divider over the resource filters to show it: the drawn panel
   heads every filter with a divider and the divider's own top margin was doing
   the work, so a toggle row followed straight by a field closed to nothing. */
.form-toggles {
  display: flex;
  flex-wrap: wrap;
  gap: var(--u2);
  margin-bottom: var(--u3);
}

/* The row is one control and the halves of it share the width, which is what
   makes it read as a switch with two positions rather than as two buttons that
   happen to sit together. `flex: 1 1 0` and not a percentage: a third half
   would divide the same line without anybody coming back to change a number,
   and the basis is the only thing that would have to be wrong.

   Shorter than a button, because it is not one. A button does something and
   the press is the event; this says which half of a collection is on screen,
   and it is read far more often than it is pressed. */
.form-toggle {
  display: inline-flex;
  flex: 1 1 0;
  align-items: center;
  justify-content: center;
  gap: var(--u2);
  padding: var(--u1) var(--u3);
  border: var(--hair) solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--bg);
  box-shadow: 0 0.05rem 0 rgba(48, 55, 66, 0.08);
  color: var(--fg);
  cursor: pointer;
  line-height: var(--lh);
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s;
  white-space: nowrap;
}

.form-toggle > input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.form-toggle:hover {
  border-color: var(--line-strong);
  background: var(--bg-sunken);
  color: var(--fg-strong);
}

.form-toggle:has(:checked) {
  border-color: var(--line-strong);
  background: var(--line-soft);
  box-shadow: inset 0 0.12rem 0.18rem rgba(48, 55, 66, 0.25);
  color: var(--fg-strong);
  font-weight: 600;
}

.form-toggle:has(:focus-visible) {
  outline: 0.1rem solid var(--primary);
  outline-offset: 0.1rem;
}

.form-toggle .count {
  color: var(--fg-faint);
}

.form-toggle:has(:checked) .count {
  color: var(--fg-muted);
  font-weight: 400;
}

/* One field per row. Always.

   A form is filled top to bottom and a single column is one path for the eye
   instead of a zigzag; it also means adding a field in the middle of a section
   moves nothing sideways further down. There is no grid to derive, no width to
   configure, and nothing to explain.

   The row is one field — the control inside it is still sized to what it
   holds. A date picker stretched across half a screen is a lie about how much
   a date is, so the two kinds of value that are never long get a width of
   their own, and a boolean gets none at all because it is a checkbox. */
.form-input-narrow {
  max-width: 10rem;
}

/* An input with a fixed tail. A company's address is one label of a hostname
   and the rest of the hostname is not the person's to type — so the control
   shows the whole thing and lets them write the only part that is theirs.

   It replaces a hint that could not be written: "the company will live at
   meridian.wf.local" needs a value to name, and before anything is typed there
   is none, which is how such a hint degrades into prose that says nothing. The
   tail is also what makes "not changeable later" land, because the address
   being made is on screen while it is being made.

   It takes no width of its own, and that is a trade. Capped, it sits the tail
   beside the value, which is the nicer reading of one control; uncapped, every
   control in the column shares a right edge, and a ragged edge down a form
   costs more than the gap inside one box buys. Rule 7's narrow widths are for
   values that are never long — a number, a date — and an address is not one of
   them. */
.form-affixed {
  display: flex;
  align-items: stretch;
  border: var(--hair) solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface);
}

.form-affixed:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 0.1rem rgba(79, 79, 187, 0.2);
}

.form-affixed .form-input,
.form-affixed .form-input:focus {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.form-affix {
  flex: none;
  align-self: center;
  padding-right: var(--u2);
  color: var(--fg-muted);
  font-family: var(--mono);
}

/* The tail can be an action instead of a label. Same box, same edge as the
   fields above it, so a column of three reads as three rows of one thing
   rather than two fields and a loose line of text. */
.form-affixed .btn {
  flex: none;
  align-self: center;
  margin-right: var(--u1);
}

/* A value stated where a control would be. It keeps the box because the row
   carries an action on it, and it takes the sunken ground because that is
   already what this design system uses to say "not typed here" — without it
   the box is a readonly input, which still claims to be a value somebody may
   revise. */
.form-affixed.is-static {
  background: var(--bg-sunken);
  border-color: var(--line);
}

.form-static {
  flex: 1 1 auto;
  padding: var(--u2);
  color: var(--fg-strong);
  line-height: var(--lh);
}

/* NOT a layout of fields: a strip of controls in a panel foot — add an option,
   grant a competence, assign a role. The from/to pair of a filter was one of
   these and is `.form-range` below, which is the same idea with the width
   taken out of it. */
.form-inline {
  display: flex;
  flex-wrap: wrap;
  gap: var(--u2);
}

.form-inline .form-group {
  flex: 1 1 12rem;
  margin-bottom: 0;
}

/* The button lines up with the control, not with the label above it. A strip
   is a labelled field beside a bare button, and the flex default stretches the
   button to the height of both rows — which draws a control twice the height
   of the one it acts on. The mockups wrote this inline on both strips that
   have one, and they were right to. */
.form-inline {
  align-items: flex-end;
}

/* THE FROM/TO PAIR OF ONE FILTER. Two across, always: they are the two ends of
   one quantity, and a pair that wraps is two boxes a reader has to work out
   are related — a panel of four ranges becomes a column of eight identical
   inputs.

   `.form-inline` is the strip these were drawn in and it cannot do it. Its
   12rem basis is right for a panel foot, where a labelled field stands beside
   a button on the width of the surface, and too wide for the filter column:
   `--side-width` is 22rem, so two of them plus the gap want 25rem inside 20rem
   and wrapped. The drawing shows them side by side and never did either, which
   is where the number came from. A grid of two equal tracks asks for no basis
   and has no width to get wrong. */
.form-range {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--u2);
}

.form-range .form-group {
  margin-bottom: 0;
}

/* Colour on a value that is not a chip and not a whole notice: the one
   digest that no longer matches, the one count that is over. Both examples
   are bad news, and so is every caller — the optimistic twin was written and
   never used, so it is not here. */
.is-bad { color: var(--bad); }

.form-error {
  margin-top: var(--u1);
  color: var(--bad);
  font-size: var(--fs-sm);
}

.form-group.has-error .form-input,
.form-group.has-error .form-select,
.form-group.has-error .form-affixed {
  border-color: var(--bad);
}

/* The affixed input has no border of its own — the wrapper carries it — so it
   must not carry the error colour either, or the box gains an inner outline. */
.form-group.has-error .form-affixed .form-input {
  border-color: transparent;
}

.form-actions {
  display: flex;
  align-items: center;
  gap: var(--u2);
  margin-top: var(--u4);
  padding-top: var(--u3);
  border-top: var(--hair) solid var(--line-soft);
}

.form-actions .spacer {
  flex: 1 1 auto;
}

/* --------------------------------------------------------------------------
   14. Notices
   -------------------------------------------------------------------------- */

.notice {
  padding: var(--u2) var(--u3);
  border-left: 0.2rem solid var(--fg-faint);
  border-radius: var(--radius);
  background: var(--bg-sunken);
}

.notice-ok {
  border-left-color: var(--ok);
  background: var(--ok-wash);
}

.notice-warn {
  border-left-color: var(--warn);
  background: var(--warn-wash);
}

.notice-bad {
  border-left-color: var(--bad);
  background: var(--bad-wash);
}

.notice .witness {
  margin-top: var(--u1);
  padding-left: var(--u4);
  list-style: none;
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

.notice h3 {
  margin-bottom: var(--u1);
  font-size: var(--fs);
}

.notice ul {
  list-style: disc;
  padding-left: var(--u5);
}

/* A sentence after the list: what to do about the findings, when there is
   something to do. The base gives a paragraph no top margin, so without this
   it welds itself to the last item. */
.notice ul + p {
  margin-top: var(--u2);
}

.empty {
  padding: var(--u8) var(--u5);
  border: var(--hair) dashed var(--line);
  border-radius: var(--radius);
  color: var(--fg-muted);
  text-align: center;
}

.empty .empty-icon {
  font-size: 2.2rem;
  line-height: 1;
}

.empty .empty-title {
  margin-top: var(--u3);
  color: var(--fg-strong);
  font-weight: 600;
}

/* The sentence under the title. The mockups wrote its measure and its centring
   inline on every one of the fourteen empty states; it is the same sentence
   shape every time, so it is one rule. */
.empty p {
  max-width: 36rem;
  margin: var(--u2) auto 0;
}

.empty .empty-actions {
  margin-top: var(--u5);
}

/* Nothing is missing here — something is being withheld. The dashed border is
   how a list says it is empty, and a refusal is not an empty list, so the one
   page that is a refusal draws a solid one. `forbidden.html` wrote it inline;
   it is a state of the component and it has a name. */
.empty.empty-solid {
  border-style: solid;
}

/* --------------------------------------------------------------------------
   15. The queue
   -------------------------------------------------------------------------- */

.queue {
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}

/* Three stacked facts on the left — what, where, what is asked — and the
   standing of the row on the right, spanning all three. Placement is written
   out rather than left to auto-flow: a row whose fourth child lands in the
   second column of the first line is a row that reflows the moment somebody
   omits one of the four. */
.queue-item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--u1) var(--u4);
  padding: var(--u3);
  border-left: 0.25rem solid var(--state, transparent);
  color: var(--fg);
}

.queue-item + .queue-item {
  border-top: var(--hair) solid var(--line-soft);
}

.queue-item:hover {
  background: var(--primary-wash);
  text-decoration: none;
}

.queue-item .queue-subject {
  grid-area: 1 / 1;
  color: var(--fg-strong);
  font-size: var(--fs-lg);
  font-weight: 600;
}

.queue-item .queue-where {
  grid-area: 2 / 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--u1) var(--u2);
  color: var(--fg-muted);
}

.queue-item .queue-ask {
  grid-area: 3 / 1;
  color: var(--fg);
}

.queue-item .queue-aside {
  grid-area: 1 / 2 / 4 / 3;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--u1);
  text-align: right;
}

/* --------------------------------------------------------------------------
   16. The board — one band per stage, in the order the process runs them

   Columns are how a board is usually drawn and are what this was. They spend
   the wrong axis. Eight stages put the fourth one off the right edge, so
   reading a process end to end meant finding a horizontal scrollbar; and every
   stage got the same 15rem whether it held nine cards or none, so a busy stage
   grew downwards beside seven columns of white.

   A band spends the width instead. The heading names the stage, the tiles
   wrap in rows beneath it, a rule closes it off from the next, and the page
   scrolls the way
   every other page in the product scrolls. There is still no drag-and-drop and
   there will not be: a card moves through a transition, and dragging one
   between stages would be a lie about the model dressed up as a convenience.
   -------------------------------------------------------------------------- */

.board {
  display: flex;
  flex-direction: column;
  gap: var(--u4);
}

/* The band wears the stage's hue, which is an attribute of the stage rather
   than a rule keyed on its slug. Two stages of one process may share one — a
   unique constraint would stop a board at the twelfth stage — and a second
   company's board is in colour because of it.

   A column carried the hue as a top rule because it capped a box. A band has no
   box, and the rule used to go under the heading, where it cut the name off
   from the very cards it names: every line on the board sat between a stage
   and itself. It closes the band instead, under its tiles, so it is the line
   between this stage and the next; the last band has no next and no rule. */
.board-stage:not(:last-child) {
  padding-bottom: var(--u4);
  border-bottom: 0.15rem solid var(--state, var(--line));
}

.board-stage > header {
  display: flex;
  align-items: center;
  gap: var(--u2);
}

/* The count stands beside the name and not at the far edge of the page. In a
   15rem column the two were a few pixels apart whichever way it was written;
   across a whole window, pushed right, the number is a figure with nothing
   next to it saying what it counts. */
.board-stage > header h3 {
  font-size: var(--fs);
}

/* auto-FILL and not auto-fit: a stage holding one card gets one tile at the
   left, not a single card stretched across the window. */
.board-stage > ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--u2);
  padding-top: var(--u3);
}

/* An empty stage says nothing where its first tile would have been. It is not
   centred any more, because there is no box left to centre it in. */
.board-stage .board-empty {
  padding-top: var(--u3);
  color: var(--fg-faint);
  font-size: var(--fs-sm);
}

/* A grid row stretches its items, so the tiles of one row are as tall as the
   tallest thing in it. The meta line takes that slack and sits at the bottom
   of the tile, so a row's keys and times read along one line instead of
   stepping. */
.card-tile {
  display: flex;
  flex-direction: column;
  gap: var(--u1);
  padding: var(--u2);
  border: var(--hair) solid var(--line-soft);
  border-left: 0.2rem solid var(--state, var(--line));
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--fg);
}

.card-tile:hover {
  border-color: var(--primary);
  box-shadow: var(--shadow);
  text-decoration: none;
}

.card-tile .tile-title {
  color: var(--fg-strong);
  font-weight: 600;
}

.card-tile .tile-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--u1) var(--u2);
  margin-top: auto;
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   17. Audit — the record's own history, in the right column

   BCC's chat, doing our job: an entry is an author, a time and what moved.
   A value that changed is shown as it moved, del then ins, never as prose.
   -------------------------------------------------------------------------- */

.audit {
  display: flex;
  flex-direction: column;
}

.audit-day {
  position: sticky;
  top: var(--panel-head-h);
  z-index: 1;
  padding: var(--u1) var(--u3);
  border-top: var(--hair) solid var(--line-soft);
  border-bottom: var(--hair) solid var(--line-soft);
  background: var(--bg-sunken);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.audit-day:first-child {
  border-top: 0;
}

.audit-day + .audit-entry {
  border-top: 0;
}

.audit-entry {
  padding: var(--u2) var(--u3);
  border-left: 0.25rem solid transparent;
  border-top: var(--hair) dashed var(--line-soft);
}

.audit-entry:first-child {
  border-top: 0;
}

.audit-entry.is-agent {
  border-left-color: #a8c8e8;
}

.audit-entry.is-decision {
  border-left-color: #cbb2e8;
}

.audit-entry.is-system {
  border-left-color: var(--line);
}

.audit-entry .audit-who {
  display: flex;
  align-items: baseline;
  gap: var(--u2);
}

.audit-entry .author {
  color: var(--fg-strong);
  font-weight: 600;
}

.audit-entry .timestamp {
  color: var(--fg-faint);
  font-size: var(--fs-sm);
  font-style: italic;
}

.audit-entry .audit-what {
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

.audit-entry .audit-change {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--u1);
  margin-top: var(--u1);
}

.audit-entry .audit-field {
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

.audit-entry .audit-note {
  margin-top: var(--u1);
  color: var(--fg);
}

/* --------------------------------------------------------------------------
   18. Page-level tabs — filters of a collection, answering to params
   -------------------------------------------------------------------------- */

.page-tabs {
  display: flex;
  gap: var(--u1);
  margin-bottom: var(--u3);
  border-bottom: var(--hair) solid var(--line);
}

/* The mockups draw the row as `nav > a`; `scope_tabs` writes `ul > li > a`,
   which is the list it is. The block is what makes the two the same: on an
   inline anchor the vertical padding does not grow the line box, so the tab
   would sit cramped and its underline would cross the row's own border. */
.page-tabs li {
  display: flex;
}

.page-tabs a {
  display: block;
  padding: var(--u2) var(--u3);
  border-bottom: 0.15rem solid transparent;
  color: var(--fg-muted);
}

.page-tabs a:hover {
  color: var(--fg-strong);
  text-decoration: none;
}

.page-tabs a.is-current,
.page-tabs a[aria-current="page"] {
  border-bottom-color: var(--primary);
  color: var(--fg-strong);
  font-weight: 600;
}

.page-tabs .count {
  color: var(--fg-faint);
  font-family: var(--mono);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   19. The stage rail — where a card stands in its process
   -------------------------------------------------------------------------- */

.rail {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--u1);
}

.rail li {
  display: flex;
  align-items: center;
  gap: var(--u1);
  padding: 0.1rem var(--u2);
  border-radius: var(--radius);
  color: var(--fg-faint);
  font-size: var(--fs-sm);
  white-space: nowrap;
}

.rail li.is-done {
  color: var(--fg-muted);
}

.rail li a {
  color: inherit;
}

/* The same rail used for sibling navigation rather than for progress. Every
   item is simply another place, so none of them is "done" — a builder page
   that borrowed .is-done would be claiming a card had been through stages it
   has never seen. */
.rail-nav li {
  color: var(--fg-muted);
}

/* The rail stood on its side, for a narrow column. The arrow between steps is
   what a row needs and what a stack does not: read downwards, the order is the
   order already. */
.rail-stack {
  flex-direction: column;
  align-items: flex-start;
}

.rail-stack li + li::before {
  content: none;
}

.rail li.is-current {
  background: var(--state-wash);
  color: var(--state);
  font-weight: 600;
}

.rail li + li::before {
  margin-right: var(--u1);
  content: "\2192";
  color: var(--line);
}

/* --------------------------------------------------------------------------
   20. Pagination
   -------------------------------------------------------------------------- */

.pager {
  display: flex;
  align-items: center;
  gap: var(--u3);
  margin-top: var(--u3);
  color: var(--fg-muted);
}

.pager .spacer {
  flex: 1 1 auto;
}

/* --------------------------------------------------------------------------
   21. Pages with no tenant behind them — the gate, and making a company

   The only pages with no toolbar: there is no tenant yet, so there are no
   sections to offer. One centred column, and nothing else on the page to
   click.

   Signing in draws nothing at all any more: `/sign_in` is a redirect on both
   hosts that have one, and the screen somebody actually answers is the
   provider's. What the card is left with is the two ends of a session — being
   refused on the way in, and being put out on the way back. The foot at the
   end of this section is the account, and it belongs here rather than to the
   list it currently stands under: the same two lines end the refusal that can
   name none of your companies.

   Making a company fits in neither — it has a form, what the company will be,
   and the identity it is being made under — and lives in `.split`, further
   down.
   -------------------------------------------------------------------------- */

.gate {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: var(--u5);
  background: var(--bg);
}

.gate-card {
  width: 100%;
  max-width: 24rem;
  padding: var(--u6);
  border: var(--hair) solid var(--line);
  border-top: 0.2rem solid var(--primary);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  text-align: center;
}

.gate-card.is-refused {
  border-top-color: var(--bad);
}

.gate-mark {
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  margin: 0 auto;
  border-radius: var(--radius);
  background: var(--primary);
  color: #fff;
  font-size: var(--fs-h1);
  font-weight: 700;
}

.gate-card.is-refused .gate-mark {
  background: var(--bad);
}

.gate-company {
  margin-top: var(--u3);
  color: var(--fg-strong);
  font-size: var(--fs-h2);
  font-weight: 600;
}

.gate-host {
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

/* The host is an address, not a snippet: the code wash shouts here. */
.gate-host code {
  background: none;
  color: inherit;
  padding: 0;
}

/* The refusal's sentence, between the address and whatever is offered next.
   The base gives a paragraph a bottom margin and no top one, so without this
   the sentence welds itself to the host line above it — which is where the
   mockup wrote `style="margin-top:1.04rem"`, and 1.04rem is --u4. Scoped to a
   direct child so that the paragraphs inside `.gate-foot` keep their own
   rhythm. */
.gate-card > p {
  margin-top: var(--u4);
}

.gate-card .btn,
.btn-block {
  width: 100%;
  justify-content: center;
}

.gate-card .btn {
  margin-top: var(--u5);
}

/* MAKING A COMPANY IS THE OTHER PAGE WITH NO TENANT BEHIND IT, and it does
   not fit in a card: it has a form, the numbers the company will start with,
   and the identity it is being made under. So the screen is two halves —
   what you are about to get on the left, what you have to type on the right.

   The halves are told apart by their ground and by nothing else: the left is
   sunken, the right is the surface a person writes on. No card inside either,
   because a bordered box on a white half is a box inside a box, and no second
   border anywhere: the seam IS the hierarchy. The right half is the only
   place on the screen with anything to do.

   Both columns hug the seam rather than their own outer edge, so on a wide
   screen the two blocks read as one object with a fold down the middle
   instead of two things that drifted apart. Under 62rem there is no room for
   two of anything and they stack FORM FIRST — side by side there is no order
   and the information half can lead, stacked there is one and it is the page's
   obligation. The media query at the end of this section is where that
   happens. */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 100vh;
}

/* The halves stay stretched so their grounds run the whole height — the seam
   is the hierarchy and a seam that stops two thirds down is not one. What
   centres is the writing inside them, and it centres with auto margins rather
   than `justify-content`, because an auto margin never pushes the top of a
   block off the scrollable area when the content is taller than the window.
   The padding is what it cannot come closer than. */
/* `min-width: 0` because a grid track sized `1fr` takes its automatic minimum
   from its contents, and a half's contents must never be what the page is as
   wide as. It was the board that proved it: three columns that could not
   shrink held the track at 381px, so on a 375px phone the whole document was
   wider than the window and every field in the OTHER half ran off the right
   edge. Bands shrink, so the widest unshrinkable thing here is now one tile at
   70% — 168px, under every phone — and this line is what keeps the question
   from being asked again. */
.split-aside,
.split-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: calc(var(--u8) * 2) var(--u8);
}

.split-inner {
  margin-top: auto;
  margin-bottom: auto;
}

/* DARK, AND THE ONLY DARK GROUND IN THE PRODUCT THAT IS NOT CHROME. It is the
   brand's own treatment — the mark lives on near-black with light type — and
   it is the reason the copper in the ground finally reads: copper carries on
   near-black and dies on cool grey.

   It also settles which half has the work on it without a single border. A
   white half beside a dark one is not two panels, it is a page and its
   shoulder.

   Nothing here overrides a component. It redefines the ink and line tokens for
   this one subtree, so every class inside — the lead, the terms, the rules —
   follows without knowing it is on a dark ground. The board figure resets them
   again, because the product is light and showing it any other way would be a
   picture of a product we do not have. */
.split-aside {
  --fg: #c9d2de;
  --fg-strong: #f2f4f8;
  --fg-muted: #93a1b4;
  --line-soft: rgba(255, 255, 255, 0.14);

  position: relative;
  overflow: hidden;
  background: var(--chrome);
  color: var(--fg);
}

/* The image is a brand photograph and the ground under it is the same
   near-black, so the two meet with no seam and the half looks right at any
   width — including the width where there is no image at all, because the
   page must not depend on a file that is somebody else's to make. It is
   anchored left because that is where this column has no writing: the writing
   hugs the seam.

   The one thing it may never do is compete with the board. The board is the
   product and the lit object; a photograph that draws the eye first has turned
   the page into an advertisement for itself.

   It is not here yet, and the ground is the whole of the rule until it is.
   `img/brand.jpg` does not exist, and Propshaft leaves an unresolvable url()
   exactly as written — so shipping the declaration would have every visit to
   this page fetch a file that answers 404. The half stands on --chrome, which
   the drawing itself says it must survive on. */


.split-aside .split-inner {
  position: relative;
}

.split-main {
  background: var(--surface);
}

.split-inner {
  max-width: 23rem;
}

/* Each half hugs the seam. In a column flexbox the horizontal one is the
   cross axis, so this is the same auto-margin trick lying on its side. */
.split-aside .split-inner {
  margin-left: auto;
  margin-right: 0;
}

.split-main .split-inner {
  max-width: 25rem;
  margin-left: 0;
  margin-right: auto;
}

.split-title {
  margin: var(--u3) 0 0;
  font-size: var(--fs-h1);
  font-weight: 600;
}

/* One line under the title, and only here: this reader has never seen the
   product, is being told to make a thing, and has not been told what the thing
   is. It says what a company IS. Why they would want one belongs on a
   website. */
.split-lead {
  margin: var(--u1) 0 0;
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

/* A named block inside a half. Plain text, not the `.divider` rule — that is
   rail furniture and comes set in spaced capitals, which on a page with one
   rule on it is the loudest thing on the screen and it is a label. */
.split-group {
  margin-top: var(--u6);
  padding-top: var(--u5);
  border-top: var(--hair) solid var(--line-soft);
}

/* Quieter than the terms under it. The heading is a label and the terms are
   the content; set at the same weight it reads as a fifth entry. */
.split-group h2 {
  margin: 0 0 var(--u4);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  font-weight: 600;
}

/* THE PRODUCT, SMALL, AND NOT A PICTURE OF IT. A board drawn with the board's
   own classes at 70%.

   It is the product itself rather than an illustration or a screenshot, and
   both of those alternatives fail in ways worth naming. An illustration of
   work moving — arrows, boxes, a cheerful abstraction — would be the one thing
   on this page that carries no information, and it is the first thing to look
   dated. A screenshot is a file that goes stale the day the board changes and
   nobody notices for a year. This goes stale never: change `.board-stage` and
   this changes with it, because it IS a `.board-stage`.

   NOTHING ARRANGES IT AND NOTHING CUTS IT. While the board was columns this
   figure was a fragment on purpose — wider than the half it sat in, painting
   past the prose, with `.split-aside` ending it at the fold so it read as a
   piece of something larger rather than a board with three stages in it. Every
   line that managed that overflow is gone, because a band is as wide as
   whatever holds it: the figure is three stages and the whole of each, and the
   only thing left to say is how big. */
.split-figure {
  margin: var(--u5) 0;
}

/* The product is light. On the dark half it is the one lit object, which is
   the honest arrangement: this is what the reader is about to be handed — so
   the half's palette is reset here rather than overridden component by
   component.

   The ground comes with the palette, and it has to: a band has no box of its
   own, so on the dark half its heading was near-black ink on near-black and
   the stage names vanished. Columns hid it — each one carried a sunken ground
   and a white header, and the figure could stand on the dark with no ground at
   all. The board's real ground is the surface it sits on inside a tenant, and
   that is what this puts under it. */
.split-figure .board {
  --fg: #455060;
  --fg-strong: #303742;
  --fg-muted: #7c8797;
  --line: #bcc3ce;
  --line-soft: #d4d8e0;
  padding: var(--u4);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--fg);
  zoom: 0.7;
}

.split-figure figcaption {
  margin-top: var(--u3);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

/* Term and description, which is what this is — no cards, no grid, no icons.
   Each term names a thing the company holds and each description says what it
   is in the reader's words. It is a definition list because that is the shape
   of the content; anything with a border around each entry would be dressing
   three sentences as three objects. */
.split-list {
  margin: 0;
}

.split-list dt {
  margin-top: var(--u4);
  color: var(--fg-strong);
  font-weight: 600;
}

.split-list dt:first-child {
  margin-top: 0;
}

.split-list dd {
  margin: var(--u1) 0 0;
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}

@media (max-width: 62rem) {
  .split {
    grid-template-columns: 1fr;
    min-height: 0;
  }

  .split-aside,
  .split-main {
    padding: var(--u6) var(--u5);
  }

  .split-aside {
    border-top: 0;
  }

  /* The form first when they stack. Side by side there is no order and the
     information half can lead; stacked there is one, and it is the page's
     obligation — making somebody scroll past eight numbers to reach the two
     fields they came to fill is the whole of what rule 5 forbids. */
  .split-main {
    order: -1;
  }

  /* `width: 100%` and not only `max-width`. The auto margins that hug the seam
     on a wide screen stop the item stretching, so its cross size is fit-content
     — which clamps up to min-content, and min-content used to be the board at
     381px of three columns that could not shrink: below about 402px the prose
     was dragged out to that width inside a narrower column and cut mid-word by
     the clip the bleed needed. An iPhone SE is 375. The board is bands now and
     its min-content is one tile, so nothing here can do that any more; the
     definite width is what says the column is the half's and not its
     contents'. */
  .split-inner {
    width: 100%;
    max-width: 30rem;
    margin: 0 auto;
  }

  .split-main .split-inner,
  .split-aside .split-inner {
    margin-left: auto;
    margin-right: auto;
  }
}

.gate-foot {
  margin-top: var(--u4);
  padding-top: var(--u3);
  border-top: var(--hair) solid var(--line-soft);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
  text-align: left;
}

/* Taken from the mockups' `.companies` section at 157e412, because Core writes
   the markup for these two now — not because that page has been redrawn, which
   it has not: it is still a table under a tenant's chrome. Both rules are
   self-contained, so they land without the family around them, and the refusal
   is the second page the comment below names — it gets this foot when it gets
   its doors. */

/* The account, and the way out beside it. Two pages end this way — the list
   of your companies, and the refusal that names none of them — because both
   are read by somebody asking "so which address am I?", and on both that is
   the thing to act on rather than to know. */
.signed-in {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--u2);
}

/* The account, last. A reader scans the list first and only looks for a
   reason when a company they expected is not in it — and the reason is nearly
   always which address they signed in with. */
.companies-foot {
  margin-top: var(--u6);
  padding-top: var(--u3);
  border-top: var(--hair) solid var(--line-soft);
  color: var(--fg-muted);
  font-size: var(--fs-sm);
}


/* --------------------------------------------------------------------------
   22. What the mockups drew inline, given a name

   Three real components lived only in per-screen <style> blocks, and four
   modifiers existed only as `style=` attributes repeated across dozens of
   files. A `<style>` block in a real template is worse than a class here, and
   an inline style is a rule nobody can find twice, so both are promoted.

   Discarded on the way: the mockups' 146 `margin-top: .78rem|1.04rem|.52rem`
   attributes and their `grid-template-columns` on `.form-inline` — both are
   the mockups working around not having a wrapper, and `.surface-main > * + *`
   and `.form-inline` already own what they were reaching for.

   Their third, `align-items: flex-end`, was discarded too and should not have
   been: see `.form-inline` below.
   -------------------------------------------------------------------------- */

/* A form wraps nothing. `.surface-main > * + *` is the ONLY vertical rhythm in
   the main column, so a `<form>` between the column and its panels would kill
   every gap on the page. The mockups could not settle this — not one of the 99
   contains a form element at all.

   Two rules, and the first alone is not enough. `display: contents` stops the
   form generating a box, which is what stops it taking a margin of its own —
   but it changes box generation and NOT selector matching, so
   `.surface-main > * + *` still matches only the form and still never matches
   the panels inside it. Without the second rule a refused save prints its
   findings notice welded to the panel head below it, which is what it did on
   all five form screens until somebody looked at one.

   The consequence to know: a contents-display box has no layout of its own, so
   nothing may be painted on the form — no border, no background, no padding.
   Nothing wants to. */
.surface-main > form {
  display: contents;
}

.surface-main > form > * + * {
  margin-top: var(--u5);
}

/* A body with no right column. Thirty mockup screens wrote this as
   `style="display:block"` on `.surface-body`; it is the archetype's full-width
   variant and it has a name now. */
.surface-body-wide {
  display: block;
}

/* The right column stacks like the main one. `.surface-main > * + *` was
   written for the column that always holds several things; the right column
   held exactly one panel on every screen drawn until the queue, which is the
   first to put two there — how to narrow the list, and what makes work reach
   this person at all. Two panels with nothing between them read as one panel
   with a rule through it.

   Written against the panels and not against `> * + *`, because `.side-close`
   is the aside's first child and is `display: none` above 1120px: a sibling
   rule would give the first panel a top margin that only exists on the wide
   layout, and the column would sit a step lower than the one beside it. The
   mockups wrote this as `style="margin-top:.78rem"` on the second panel, which
   is this number. */
.surface-side .panel + .panel {
  margin-top: var(--u3);
}

/* The sentence a collection opens with, capped at the measure prose is read at
   rather than at the width of the surface — nine list screens wrote it as
   `style="max-width:52rem"` on a `<p class="muted">`. 52rem is `.panel-form`'s
   cap, and it is the same number for the same reason: it is how wide a line of
   words may be before the eye loses the start of the next one. */
.prose {
  max-width: 52rem;
}

/* A field list whose second column is an action rather than a value — twenty
   screens, all of them `style="grid-template-columns: 1fr auto"`. */
.fields.fields-actions {
  grid-template-columns: 1fr auto;
}

/* The one account row the mockups could not draw. Signing out is a DELETE, so
   its control is a form's button rather than a link — and not one of the 99
   mockups contains a form element, so nothing in them settled this. The row
   reads as every other row: the padding is on the control, because a menu
   entry that only answers on its words is a target the width of the word. */
.toolbar .account > ul li > form {
  display: block;
}

.toolbar .account > ul li > form > button {
  display: block;
  width: 100%;
  padding: var(--u1) var(--u2);
  border: 0;
  border-radius: var(--radius);
  background: none;
  color: var(--fg);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.toolbar .account > ul li > form > button:hover {
  background: var(--bg-sunken);
  color: var(--fg-strong);
}

/* The flash. It is news about the page rather than part of it — every screen
   can raise one and no screen owns one — so it belongs to the layout, above
   the page head and inside the surface.

   It is a bar and not a card, because everything else the layout owns is a
   bar: the toolbar above it and the page head below it both run edge to edge,
   and an inset box wedged between two of them reads as a panel that lost its
   page, with the gap above belonging to nothing. The sentence still lines up
   with the crumbs under it — the state edge is 0.2rem of the 1.3rem the head
   pads by, so the left padding gives the rest back and the text starts at the
   same 20.8px. Two flashes at once stack as two bars, which is why each one
   closes with a hairline rather than the block closing with one. */
.flash .notice {
  padding: var(--u3) var(--u5) var(--u3) calc(var(--u5) - 0.2rem);
  border-bottom: var(--hair) solid var(--line);
  border-radius: 0;
}

/* An option of a decision, on the run screen. Choosing one is the whole job of
   the page, so the target is large and obvious rather than a radio in a row.
   `.is-chosen` is SERVER-RENDERED state: it says which option this reader
   already answered, not which radio the pointer is over. A live client echo,
   if ever wanted, is `:has(:checked)` and not a controller.

   Scoped under `.options` rather than written bare as the mockup had it: Tom
   Select's dropdown calls its rows `.option` too, and a bare rule here dresses
   every entry of every searchable select in the product. The mockup could not
   have known — it vendors no Tom Select. */
.options {
  display: flex;
  flex-direction: column;
  gap: var(--u2);
}

.options .option {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--u3);
  align-items: start;
  padding: var(--u3);
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
}

.options .option:hover {
  border-color: var(--primary);
  background: var(--primary-wash);
}

.options .option.is-chosen {
  border-color: var(--primary);
  border-left-width: 0.25rem;
  background: var(--primary-wash);
}

.options .option-label {
  color: var(--fg-strong);
  font-weight: 600;
}

.options .option-desc {
  color: var(--fg-muted);
}

/* A disclosure in the right column — the earlier stages of a card, folded.
   It is a <details>, and the marker is replaced because a folded section must
   not look like a `.panel-head`: a panel head is a place, a fold is a choice. */
.fold {
  border-top: var(--hair) solid var(--line-soft);
}

.fold:first-child {
  border-top: 0;
}

.fold > summary {
  padding: var(--u2) var(--u3);
  cursor: pointer;
  color: var(--fg-strong);
  font-weight: 600;
  list-style: none;
}

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

.fold > summary::before {
  content: "▸ ";
  color: var(--fg-faint);
}

.fold[open] > summary::before {
  content: "▾ ";
}

.fold > summary:hover {
  background: var(--primary-wash);
}

.fold > div {
  padding: 0 var(--u3) var(--u3);
}

/* A one-time secret. It is the entire content of the response it arrives in and
   it is never shown again, so it is set at a size you can read across a desk
   and select in one drag. `user-select: all` is the whole point. */
.secret {
  display: block;
  margin-top: var(--u2);
  padding: var(--u3);
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--code-fg);
  font-family: var(--mono);
  font-size: 1rem;
  line-height: 1.6rem;
  word-break: break-all;
  user-select: all;
}

/* A mutation is a <form>, and every row of buttons in this file is a flex box.

   The mockups contain no form element, so nothing in them settled this — but
   the builder does the settling for them: it holds no client state and has to
   work with no script running at all, so a control that PATCHes is a form's
   button and never a link with a `data-turbo-method`. Left as a block, that
   form becomes the flex item and the button inside it stops taking part in the
   row's gap and alignment. `display: contents` hands the button straight to
   the row, the same trick `.surface-main > form` plays for the whole column.

   Not `.btn-group form`: an arrow strip is written as ONE form with two submit
   buttons, because `:first-child`/`:last-child` are what join the pills and a
   button alone in its own form is both.

   Same consequence as the other contents box: nothing may be painted on the
   form. Nothing wants to. */
.page-actions form,
.form-actions form,
.panel-head form,
.panel-foot form {
  display: contents;
}

/* The right column stacks its panels the way the main column stacks
   everything, and the mockups wrote it as `style="margin-top:.78rem"` on every
   panel after the first — eleven screens, one number. The step is smaller than
   `.surface-main`'s on purpose: the drawer is narrow and its panels read as
   one list rather than as separate blocks. */
.surface-side > * + * {
  margin-top: var(--u3);
}

/* The four `style=` attributes the split page carries, given a name. This is
   the one archetype with no column rule behind it — `.surface-main > * + *`
   is what spaces everything on every other page, and there is no surface here
   — so each of these is doing work rather than working around a wrapper,
   which is why they are kept instead of discarded with the other 146. */
.split-main .notice {
  margin-bottom: var(--u5);
}

.split-main .btn-block {
  margin-top: var(--u6);
}

/* What the button does, under the button. Further from it than a hint is from
   its input, because it answers the action rather than a value. */
.split-main .btn-block + .form-hint {
  margin-top: var(--u2);
}

/* The closing line stands clear of the terms above it: it is about the company
   rather than about what is inside one. */
.split-aside .split-group + p {
  margin-top: var(--u6);
}

/* A choice that narrows the one above it — "updated", then "in any field" or
   "in any of these fields", then the fields — stands one step in under it.
   The trigger's configuration page wrote it as `style="margin-left:1.56rem"`
   at both depths: the width of a checkbox and its gap, so what narrows lines
   up under the caption of what it narrows. */
.form-checks-nested {
  margin-left: var(--u6);
}

/* --------------------------------------------------------------------------
   23. Tom Select, fitted to these tokens

   The vendored control generates its own DOM and `tom-select.css` still ships
   it. Nothing above styles a `ts-*` class, so these rules are the whole
   adaptation, and they belong here rather than beside the vendored file for
   the same reason every other token consumer does: this is where our numbers
   are. The plain `<select multiple>` underneath is the fallback and it is
   already `.form-select`.

   Two of them are about the vendored sheet rather than about our tokens, and
   both only became true when a multiple select first wore the decoration: one
   has to match a vendored selector's weight to win, and one has to name a
   place on our stacking scale, because the generated list is in the document
   where the native list box never was.
   -------------------------------------------------------------------------- */

.ts-wrapper {
  max-width: 34rem;
}

.ts-wrapper.multi .ts-control > div {
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
}

/* The remove action of a tag has to be findable without hovering, so it gets a
   rule separating it from the label. `:not(.rtl)` is not a condition this
   needs — it is the vendored selector's, carried here to match its weight.
   Without it the rule is one class lighter, loses, and the separator is drawn
   in the vendor's own grey while the tag beside it is drawn in ours. It was,
   for as long as this section has existed. */
.ts-wrapper.plugin-remove_button:not(.rtl) .item .remove {
  border-left-color: var(--line);
}

/* Above a sticky table head, below the toolbar's scrim.
   The vendored `.ts-dropdown` asks for 10 and the browser used to draw the
   list box as widget chrome, in front of everything — so nothing had to be
   said. Decorated, the list is in the document, and the one control that
   wears this decoration sits directly above a table whose `thead th` is
   sticky at 20: an option was painted behind the header and could not be
   clicked. 25 clears it and still passes under the account menu's scrim at
   35, which has to cover the page whole. */
.ts-dropdown {
  z-index: 25;
}

/* Focus reads the same as every other control's: the border takes the accent
   and a 0.1rem wash sits outside it. Not an `outline` — the vendored control
   already draws its own box, and two rings on one field is one too many. */
.ts-wrapper.focus .ts-control {
  border-color: var(--primary);
  box-shadow: 0 0 0 0.1rem rgba(79, 79, 187, 0.2);
}

/* --------------------------------------------------------------------------
   24. The popup — one question, in front of the page

   The platform's own: `popover` on the box and `popovertarget` on whatever
   opens it. No controller, for the same reason the account menu is a
   <details> — the top layer, light dismiss and Escape are the browser's, and
   a script that reimplemented them would be a script on every page carrying
   one popup.

   Three facts about the box that are the browser's and not this file's, worth
   knowing before adding a rule here. A closed popover is `display: none`, so
   it is not a flex item and a head that holds one has no gap where it stands.
   An open one is `position: fixed` against the viewport and centred by the UA's
   `inset: 0; margin: auto` — which the column it is written in can take away,
   so the margin is restated below and a width is the rest of positioning it.
   And it
   sits in the top layer, above every z-index and outside every ancestor's
   overflow — which is what makes it safe to write inside a sticky head.

   `background` and `color` are declared because the UA's are `canvas` and
   `canvastext`: a popup left to those is white-on-black in a dark browser
   theme on a page that has no dark theme. Section 1's palette is the whole
   page or none of it.
   -------------------------------------------------------------------------- */

.popup {
  /* Two rules undoing where the popup was written, because a popup is declared
     next to the thing it is about and drawn in front of the whole page: the
     top layer takes it out of the LAYOUT, not out of the cascade.

     `margin` is the UA's own, restated: `.surface-main > * + *` is written
     against ANY sibling, so a popup standing among that column's panels took
     `margin-top: var(--u5)`, lost the auto that centres it and hung at the top
     of the viewport over the toolbar. `text-align` because one of them sits in
     a `td.right` and came out right-aligned. A popup is placed by the viewport
     and never by where it was written. */
  margin: auto;
  text-align: left;
  width: min(26rem, calc(100vw - var(--u8)));
  padding: var(--u4);
  border: var(--hair) solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow);
}

/* The page dimmed behind it. It does not block a click — light dismiss is what
   an outside click is for — it says which of the two layers is being read. */
.popup::backdrop {
  background: rgba(48, 55, 66, 0.35);
}

.popup-title {
  margin-bottom: var(--u2);
  color: var(--fg-strong);
  font-size: var(--fs-h3);
}

/* --------------------------------------------------------------------------
   25. Paper

   Two rules, carried forward from `panel.css`, which had them for a reason
   worth keeping: navigation does not belong on paper, because a printed page
   carrying a row of links nobody can follow is a row of noise. `simple.css`
   said it about `body > header nav` and was overruled by the sheet that turned
   the banner into a toolbar — same specificity, later file — so the toolbar
   printed its menu all along.

   The head itself stays, because it is where the page's name lives now. What
   goes with the toolbar is everything in it that is a control: the pages of
   the subject, the way back, the scope menu and the actions. The trail and
   the subject print, and they are the only thing on the sheet that says what
   was printed.

   And that is all of print. Everything in sections 3 through 21 is
   print-hostile: `.toolbar` is a dark ground that will not adjust; the page
   head, the table head, `.audit-day` and the right column's panel heads are
   all `position: sticky`; `.surface-side` and `.board` are scroll containers
   that clip what they hold; and the state edge carries meaning that a
   colour-stripped print drops entirely. A printable card, record read-back or
   audit trail is real work against those five facts and it was not attempted.
   -------------------------------------------------------------------------- */

@media print {
  .toolbar,
  .page-head .page-back,
  .page-head .page-pages,
  .page-head .page-actions,
  .page-head .scope {
    display: none;
  }
}
