/* ERProduce — Direction D.
   The official visual direction, approved 2026-09-15 and recorded in DESIGN.md.
   Ported from the approved prototype .impeccable/mocks/ux-1/d-modern/d.css into
   the product's own screens. Modern and airy: white cards with 12px corners and
   a soft shadow on the painted ground, a real sidebar, a header that names the
   company, buttons that look like buttons. No framework, no CDN, no web font,
   no icon font, no dark mode, no JavaScript required by anything here.

   Measured contrast against --ground #f2f0eb (WCAG 2.2 relative luminance).
   tests/test_45_accessibility.py recomputes every one of these from the tokens
   below, so a token cannot drift away from the number written here.

     --ink        #15181a   15.66:1   text
     --structure  #1b4d8f    7.36:1   text, focus ring, the intact condition
     --refusal    #8c2a17    7.50:1   text, the blocked condition
     --quiet      #4a5157    7.08:1   sub lines and muted notes: still body
                                      text, so still held to 4.5:1
     --rule       #8a8377    3.30:1   1.4.11 non-text. It separates rows in a
                                      tray of two hundred, which is not
                                      decoration, so it does not take that
                                      exception.
     --action     #f2b705    1.60:1   never a boundary and never text on the
                                      ground. The control is bounded by its own
                                      border and its label is --ink on yellow
                                      (9.81:1).

   The file ends with a marked retiring section. It exists because this phase
   rebuilds one screen at a time: a screen that has not had its task yet still
   renders the UX-0B vocabulary, and leaving it unpainted would make every
   target-size guarantee true in a file and false on the glass. That section may
   only shrink, and tests/test_70_design_system.py fails if a selector in it
   outlives the template that renders it. */

:root {
  /* Painted ground, light in every mode. There is no dark panel. */
  --ground: #f2f0eb;      /* Painted Ground */
  --ink: #15181a;         /* Stencil Ink */
  --structure: #1b4d8f;   /* Marine Blue: structure, focus, a confirmed state */
  --action: #f2b705;      /* Safety Yellow: ONLY where an action is possible */
  --refusal: #8c2a17;     /* Oxide: refusal and blocked only */
  --rule: #8a8377;        /* Rule Grey: 3.30:1 on the ground */
  --quiet: #4a5157;       /* Quiet Slate */
  --field: #ffffff;       /* Field White */

  /* Tints are the same hues at low alpha, never new colours. */
  --structure-10: rgba(27, 77, 143, 0.10);
  --structure-16: rgba(27, 77, 143, 0.16);
  --action-18: rgba(242, 183, 5, 0.18);
  --refusal-10: rgba(140, 42, 23, 0.10);
  --rule-22: rgba(138, 131, 119, 0.22);
  --rule-35: rgba(138, 131, 119, 0.35);
  --ink-06: rgba(21, 24, 26, 0.06);
  --ink-18: rgba(21, 24, 26, 0.18);

  /* Direction D's spacing scale, as DESIGN.md documents it. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;

  /* ERProduce's own rule, stricter than WCAG 2.2 AA's 24x24 minimum, and the
     same at every width including the rail. */
  --target-min: 44px;

  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-pill: 999px;
  --shadow-1: 0 1px 2px rgba(21, 24, 26, 0.05), 0 1px 3px rgba(21, 24, 26, 0.06);
  --shadow-2: 0 4px 12px rgba(21, 24, 26, 0.08), 0 1px 3px rgba(21, 24, 26, 0.06);
  --sidebar: 248px;
  --header: 64px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* --- Base ----------------------------------------------------------------- */

* { box-sizing: border-box; }
html { color-scheme: light; }
body {
  margin: 0; background: var(--ground); color: var(--ink);
  font: 15px/1.5 var(--font);
  -webkit-font-smoothing: antialiased;
}

/* Links fall through to the user agent's #0000ee unless they are told
   otherwise, and that colour is not in the palette. */
a { color: var(--structure); }

h1, h2, h3 { letter-spacing: -0.01em; }
h1 { font-size: 1.5rem; font-weight: 700; margin: 0 0 var(--space-3); }
/* A void separates sections, not a hairline. */
h2 { font-size: 1.0625rem; font-weight: 700; margin: var(--space-5) 0 var(--space-3); }
h3 { font-size: 0.9375rem; font-weight: 600; margin: 0 0 var(--space-2); }
p { margin: 0; }
caption { text-align: left; padding-bottom: var(--space-2); color: var(--quiet); }

/* One label grid rules every list of labelled facts, so the eye learns the row
   once and never re-learns it. */
dl {
  display: grid;
  grid-template-columns: minmax(10rem, 14rem) minmax(0, 1fr);
  gap: var(--space-1) var(--space-3);
  margin: var(--space-3) 0;
}
dt, dd { margin: 0; }
dt { font-weight: 600; color: var(--quiet); }
dd { overflow-wrap: anywhere; }

/* Overflow containment. A digest is 64 unbroken characters. */
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.92em; overflow-wrap: anywhere; word-break: break-all; }
/* Right for a 64-character digest in a fields list, wrong in a table cell: it
   split a twelve-character checksum across two lines and doubled the height of
   every row in the tray. The table has its own scroll container for width. */
td code { word-break: normal; white-space: nowrap; }

/* Wide enough that the container scrolls rather than crushing the columns. */
table { width: 100%; border-collapse: collapse; min-width: 46rem; font-size: 0.9rem; }
th { text-align: left; font-size: 0.75rem; font-weight: 700; color: var(--quiet); text-transform: uppercase; letter-spacing: 0.04em; padding: var(--space-3) var(--space-5); border-bottom: 1px solid var(--rule-22); background: rgba(242, 240, 235, 0.55); }
td { padding: var(--space-3) var(--space-5); border-bottom: 1px solid var(--rule-22); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
/* ERProduce's own 44x44 rule reaches standalone links too. The filename in the
   tray is the only way into a document. Links inside a running sentence keep
   the standard's inline exception. */
td a { display: inline-flex; align-items: center; min-height: var(--target-min); }

/* A label is a block. Left inline, a correction form renders as one running
   line that wraps wherever it happens to run out of room. */
label { display: block; font-weight: 600; margin-bottom: var(--space-1); }
form { margin: var(--space-3) 0; }
/* `font: inherit` and `color: var(--ink)` are both here for the same reason: a
   form control inherits neither from its ancestors. */
button, input, select, textarea {
  min-height: var(--target-min);
  min-width: var(--target-min);
  font: inherit;
  color: var(--ink);
}
input[type="text"], input[type="email"], input[type="password"],
input[type="search"], input[type="tel"], input[type="url"],
input[type="number"], input[type="date"], input[type="datetime-local"],
select, textarea {
  border: 1px solid var(--rule-35); border-radius: var(--r-md);
  padding: 0 var(--space-3); background: var(--field);
  width: 100%; max-width: 34rem;
}
textarea { padding: var(--space-2) var(--space-3); }

/* Keyboard and touch. Not decoration. */
:focus-visible { outline: 3px solid var(--structure); outline-offset: 2px; border-radius: 4px; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* The first focusable thing on every page is a real target, not a 39px one:
   the product's 44px rule does not make an exception for the control a
   keyboard user meets first. */
.skip { position: absolute; left: -9999px; top: 8px; display: inline-flex; align-items: center;
        min-height: var(--target-min); background: var(--field); padding: var(--space-2) var(--space-3);
        border: 1px solid var(--rule-35); border-radius: var(--r-sm); z-index: 50; }
.skip:focus { left: 8px; }
svg.i { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
svg.i.sm { width: 16px; height: 16px; }

/* --- Layout --------------------------------------------------------------- */

.app { display: grid; grid-template-columns: var(--sidebar) minmax(0, 1fr); min-height: 100vh; }
/* The sign-in door and the chooser: no company is active, so no module map is
   asserted and the content takes the whole width. */
.app--door { grid-template-columns: minmax(0, 1fr); }
.sidebar {
  background: var(--field); border-right: 1px solid var(--rule-22);
  display: flex; flex-direction: column; padding: var(--space-4) var(--space-3); gap: var(--space-1);
  position: sticky; top: 0; height: 100vh;
}
.brand { display: flex; align-items: center; gap: 10px; padding: var(--space-2) 10px var(--space-5); text-decoration: none; color: var(--ink); }
.brand__mark { width: 32px; height: 32px; border-radius: 9px; background: var(--structure); color: #fff; display: grid; place-items: center; font-weight: 800; font-size: 15px; }
.brand__name { font-weight: 800; font-size: 1.0625rem; letter-spacing: -0.01em; }
.brand__sub { display: block; font-size: 0.75rem; color: var(--quiet); font-weight: 500; }
.nav { display: flex; flex-direction: column; gap: var(--space-1); }
/* The two navigation targets were five pixels apart once. They are their own
   group, with the spacing scale between them. */
.nav a {
  display: flex; align-items: center; gap: var(--space-3); min-height: var(--target-min);
  padding: 0 var(--space-3); border-radius: 10px; text-decoration: none; color: var(--quiet); font-weight: 600;
}
.nav a:hover { background: var(--ink-06); color: var(--ink); }
.nav a[aria-current="page"] { background: var(--structure-10); color: var(--structure); }
.sidebar__foot { margin-top: auto; padding: var(--space-3) 10px var(--space-1); display: grid; gap: var(--space-2); font-size: 0.8125rem; color: var(--quiet); }

.main { min-width: 0; display: flex; flex-direction: column; }
.header {
  min-height: var(--header); background: var(--field); border-bottom: 1px solid var(--rule-22);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); padding: var(--space-2) var(--space-6);
  position: sticky; top: 0; z-index: 20;
}
.header form { margin: 0; }
.header__right { margin-left: auto; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); min-width: 0; }
.company {
  display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--target-min); padding: 0 var(--space-3);
  border: 1px solid var(--rule-35); border-radius: var(--r-md); background: var(--field);
  color: var(--ink); font: inherit; font-weight: 600; text-decoration: none;
}
.company:hover { background: var(--ground); }
.lang { display: inline-flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.lang label { display: inline; margin: 0; font-weight: 400; }
.lang select { width: auto; min-width: 8rem; }
.user { display: inline-flex; align-items: center; gap: 10px; min-height: var(--target-min); padding: 0 var(--space-2); border-radius: var(--r-md); color: var(--ink); font-size: 0.875rem; overflow-wrap: anywhere; }
.iconbtn { display: inline-grid; place-items: center; width: var(--target-min); height: var(--target-min); border: 1px solid var(--rule-35); border-radius: var(--r-md); background: var(--field); color: var(--quiet); cursor: pointer; }
.iconbtn:hover { background: var(--ground); color: var(--ink); }

/* The off-canvas navigation, below 900px. A native <details>: no JavaScript is
   required for any function on any screen. */
.drawer { display: none; }
.drawer > summary {
  list-style: none; display: inline-grid; place-items: center;
  width: var(--target-min); height: var(--target-min);
  border: 1px solid var(--rule-35); border-radius: var(--r-md);
  background: var(--field); color: var(--ink); cursor: pointer;
}
.drawer > summary::-webkit-details-marker { display: none; }
.drawer__panel {
  position: absolute; left: var(--space-4); right: var(--space-4); top: calc(var(--header) + var(--space-2));
  background: var(--field); border: 1px solid var(--rule-22); border-radius: var(--r-md);
  box-shadow: var(--shadow-2); padding: var(--space-2); z-index: 40;
}

.content { padding: var(--space-6); display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); max-width: 1440px; width: 100%; }
.content > * { min-width: 0; }

/* --- Page head ------------------------------------------------------------ */

.pagehead { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-3) var(--space-4); }
.pagehead__text { display: grid; gap: var(--space-1); margin-right: auto; }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
/* Some controls in the row are a whole form, because a POST needs one. The
   form is the wrapper, not a block of its own: without this its margin and the
   card rule that gives a submit its own line push one button off the line its
   neighbours sit on. */
.actions form { margin: 0; }

/* --- Buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: var(--target-min); padding: var(--space-2) var(--space-4); border-radius: 10px;
  font: inherit; font-weight: 700; font-size: 0.9375rem;
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  /* A label long enough to name its field - "Correct Incoterm, as declared in
     the foreign-trade complement" - must wrap rather than push the page
     sideways on a narrow screen. The target keeps its minimum height either
     way. */
  text-align: center; max-width: 100%;
}
/* Safety yellow appears where an action is possible, once. */
.btn-primary { background: var(--action); color: var(--ink); border: 2px solid var(--ink); box-shadow: var(--shadow-1); }
.btn-primary:hover { filter: brightness(0.96); box-shadow: var(--shadow-2); }
.btn-secondary { background: var(--field); color: var(--ink); border-color: var(--rule-35); box-shadow: var(--shadow-1); }
.btn-secondary:hover { background: var(--ground); }
.btn-ghost { background: transparent; color: var(--structure); font-weight: 600; }
.btn-ghost:hover { background: var(--structure-10); }
/* The same primary control when the document is blocked or unverified:
   deliberately not yellow. Yellow marks acting on the document's content; this
   acts on the file. */
.btn-blue { background: var(--structure); color: #fff; }
.btn-blue:hover { filter: brightness(1.08); }
/* Tighter type and padding, never a smaller target: the 44 Is Ours Rule names
   table action buttons and holds at every width. */
.btn-sm { min-height: var(--target-min); padding: 0 var(--space-3); font-size: 0.875rem; border-radius: 9px; }

/* --- Cards ---------------------------------------------------------------- */

.card { background: var(--field); border: 1px solid var(--rule-22); border-radius: var(--r-md); box-shadow: var(--shadow-2); }
/* The two screens a person meets before entering a company hold one narrow
   form each. Left at full width they were a card of empty white with its
   content packed into the first third. */
.app--door .content { max-width: 34rem; margin: 0 auto; }
.app--door .pagehead { justify-content: center; }
/* The submit is its own row: an input is 34rem wide and a button is inline, so
   without this the two share a line and the button wedges against the field. */
.card__body form > .btn { display: flex; margin-top: var(--space-4); }
/* Except where the form is one control among several: there the submit is an
   item in the row and sits on the same line as its neighbours. Stated after
   the rule it corrects, and more specific, so order cannot decide it. */
.card__body .actions form > .btn { display: inline-flex; margin-top: 0; }
.card__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-4) var(--space-5) 0; }
.card__head h1, .card__head h2, .card__head h3 { margin: 0; }
.card__body { padding: var(--space-4) var(--space-5) var(--space-5); }
.card__foot { padding: var(--space-3) var(--space-5); border-top: 1px solid var(--rule-22); display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; font-size: 0.875rem; }
.card__body > dl:first-child, .card__body > p:first-child { margin-top: 0; }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-4); }

/* Stat tile. A figure is rendered only when a query produced it. */
.stat { display: grid; gap: 6px; padding: 18px var(--space-5); text-decoration: none; color: inherit; }
.stat:hover { box-shadow: var(--shadow-2); }
.stat__label { display: flex; align-items: center; gap: var(--space-2); font-size: 0.875rem; font-weight: 600; color: var(--quiet); }
.stat__value { font-size: 1.875rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; }

/* --- Badges: a compact condition, word first ------------------------------ */
/* The word is always present: a badge never depends on colour alone. Colour is
   spent only where the direction already gives it a meaning. */
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px; border-radius: var(--r-pill); font-size: 0.75rem; font-weight: 700; line-height: 1.6; white-space: nowrap; background: var(--ink-06); color: var(--ink); }
.badge__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: .85; flex: none; }
.badge-blue { background: var(--structure-10); color: var(--structure); }
.badge-red { background: var(--refusal-10); color: var(--refusal); }
.badge-grey { background: var(--ink-06); color: var(--quiet); }
/* The document's own status vocabulary, painted from the value rather than from
   a class a template assembled. Oxide is refusal; structure blue is a confirmed
   state; every other status is carried by its word. */
.badge[data-status="rejected"] { background: var(--refusal-10); color: var(--refusal); }
.badge[data-status="verified"] { background: var(--structure-10); color: var(--structure); }

/* --- Tables --------------------------------------------------------------- */

.table-wrap { overflow-x: auto; max-width: 100%; }
.row td { border-top: 0; }
.sub { display: block; color: var(--quiet); font-size: 0.8125rem; }

/* --- The condition of a stored original ----------------------------------- */
/* Three states, three treatments, and none of them a paler version of another:
   unknown carries a dashed edge because not knowing is not a weak form of
   knowing. */
.doc-status {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-4); margin: 0;
  border: 2px solid currentColor; border-radius: var(--r-pill);
  font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; font-size: 0.8125rem;
}
.doc-status[data-condition="intact"] { color: var(--structure); border-style: solid; }
.doc-status[data-condition="blocked"] { color: var(--refusal); border-style: solid; }
.doc-status[data-condition="unknown"] { color: var(--ink); border-style: dashed; }

/* --- Alerts: a refusal, or a note about the state ------------------------- */

.alert { display: grid; gap: var(--space-1); padding: var(--space-3) var(--space-4); border: 2px solid var(--rule-35); border-radius: 10px; margin: var(--space-3) 0; }
.alert > :first-child { margin-top: 0; }
.alert--refusal { border-color: var(--refusal); color: var(--refusal); }
.alert--ink { border-color: var(--ink); border-style: dashed; }

/* --- Key and value, and a person's decision ------------------------------- */

.kv { display: grid; grid-template-columns: minmax(10rem, 14rem) minmax(0, 1fr); gap: var(--space-2) var(--space-4); font-size: 0.9rem; margin: 0; }
.kv dt { color: var(--quiet); margin: 0; }
.kv dd { margin: 0; overflow-wrap: anywhere; }
/* A decision by a person is visibly not a proposal by a machine. */
.kv--decision dd { font-weight: 700; }
/* The absence of one is not a decision, so it does not take the decision's
   weight. */
.kv--decision dd .sub { font-weight: 400; }

/* --- A folded block of facts ---------------------------------------------- */
/* The same disclosure primitive everywhere, so a reader learns one control. */
.fold > summary {
  display: list-item; list-style-position: inside;
  min-height: var(--target-min); padding: var(--space-2) 0;
  cursor: pointer; font-weight: 600; color: var(--structure);
}

/* --- The Required fields still pending ------------------------------------ */
/* A key is a short token. Given a row of its own it left a column of empty
   white beside it; as a wrapped list of marks it reads as the set it is. */
.keys { display: flex; flex-wrap: wrap; gap: var(--space-2); list-style: none; margin: var(--space-2) 0 0; padding: 0; }
/* Sized by its padding, not by a minimum: a declared minimum below 44px in
   this file is a target the product's own rule would refuse, and these are
   marks rather than controls. */
.keys li { display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-3); border: 1px solid var(--rule-35); border-radius: var(--r-pill); font-size: 0.8125rem; }
/* The field's own name leads; its key travels beside it, quieter and smaller,
   as the evidence it is. */
.keys li code { color: var(--quiet); font-size: 0.75rem; }

/* --- One outcome of an upload --------------------------------------------- */

.result { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); min-height: var(--target-min); padding: var(--space-2) 0; border-top: 1px solid var(--rule-22); font-size: 0.9rem; }
.result:first-child { border-top: 0; }
.result[data-outcome="refused"] { color: var(--refusal); }

/* --- The company chooser -------------------------------------------------- */
/* The only two objects on that screen. They share an edge, which is what makes
   two of them read as one choice rather than as two unrelated controls. */
.choices { display: grid; gap: var(--space-2); justify-items: start; }
.choices .btn { width: 100%; max-width: 22rem; justify-content: flex-start; }

/* --- The honest empty state ----------------------------------------------- */
/* A title, a sentence and at most one way out. No figure is drawn when there is
   nothing to count. */
.empty { display: grid; justify-items: start; gap: var(--space-3); padding: var(--space-6) var(--space-5); color: var(--quiet); }
.empty h2 { margin: 0; color: var(--ink); }

/* --- Responsive: content-driven breakpoints -------------------------------
   >= 1200  full sidebar (248px).
   900-1199 the sidebar becomes a 72px rail of icons; every target stays 44px.
   < 900    the sidebar is off-canvas behind a native <details> drawer. */

@media (max-width: 1199px) {
  th, td { padding: var(--space-3) var(--space-4); }
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1199px) and (min-width: 900px) {
  :root { --sidebar: 72px; }
  .sidebar { padding: var(--space-4) 10px; }
  .brand { justify-content: center; padding: var(--space-2) 0 var(--space-5); }
  .brand__name, .brand__sub { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  /* The rail is icons only, and the label stays in the accessible name. Nothing
     here shrinks a target: 44px is the same at every width. */
  .sidebar .nav a { justify-content: center; padding: 0; gap: 0; min-width: var(--target-min); }
  .sidebar .nav a > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .sidebar__foot { padding: var(--space-3) 0 var(--space-1); justify-items: center; }
}
@media (max-width: 899px) {
  .app { grid-template-columns: minmax(0, 1fr); }
  .sidebar { display: none; }
  .drawer { display: inline-block; }
  .header { padding: var(--space-2) var(--space-4); gap: var(--space-2); }
  /* The stat tiles stay two per row here, as DESIGN.md's breakpoint table
     says. Dropping them to one column at 768 left three quarters of the row
     empty and pushed the table below the fold. */
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* The right group used to take a second row on its own while the first held
     only the drawer and the company. */
  .header__right { gap: var(--space-2); font-size: 0.875rem; }
  .header .lang label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .header .lang select { min-width: 6rem; }
  .content { padding: var(--space-4); gap: var(--space-4); }
  .kv, dl { grid-template-columns: minmax(0, 1fr); }
  .kv dd, dl dd { margin-bottom: var(--space-2); }
}
/* One column only below 600px, which is where two tiles stop fitting. */
@media (max-width: 599px) {
  .grid-4 { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* --- A field's value, the largest object in its card ---------------------- */
.value { font-size: 1.125rem; font-weight: 600; overflow-wrap: anywhere; margin: 0 0 var(--space-2); }

/* --- Lists of records carry no browser discs ------------------------------ */
/* Scoped by class rather than a blanket reset, so ordinary prose lists keep
   their markers. */
.history ul, .results-list { list-style: none; margin: 0; padding-left: 0; }
.results-list > li, .history li { margin: var(--space-2) 0; }

/* The two disclosures a field carries. Correction is bordered because it holds
   a form; the history is a quiet line. Both are `fold`, so a reader learns one
   control and not three. */
.correct > summary {
  display: list-item; list-style-position: inside;
  min-height: var(--target-min); padding: var(--space-2) var(--space-3);
  border: 1px solid var(--rule-35); border-radius: 10px;
  cursor: pointer; font-weight: 600; color: var(--structure);
}
.history > summary {
  display: list-item; list-style-position: inside;
  min-height: var(--target-min); padding: var(--space-2) 0;
  cursor: pointer; font-weight: 600; color: var(--structure);
}
.history { border-left: 2px solid var(--rule-22); padding-left: var(--space-3); }
/* The third disclosure a field carries: where the value came from and how
   certain the parser was. Quiet, and last, because the value and its decision
   come first. */
.evidence > summary {
  display: list-item; list-style-position: inside;
  min-height: var(--target-min); padding: var(--space-2) 0;
  cursor: pointer; font-weight: 600; color: var(--quiet);
}
.evidence .kv { font-size: 0.8125rem; }

/* The level the applied profile version records for a field. Required is the
   one that can still be owed, so it is the only one painted; Optional and Not
   Applicable are carried by their word. */
.badge[data-level="required"] { background: var(--structure-10); color: var(--structure); }

/* --- Forms ---------------------------------------------------------------
   Direction D's form vocabulary, from DESIGN.md's Components section. A
   control is 44px at every width, carries the 35% rule border and the 12px
   radius, and shows its error as a word in oxide - never as a colour alone.

   The grid is two columns where there is room and one below 700px, so a form
   stays a single readable column on a tablet held in portrait. */
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); align-items: start; }
.form-grid > .field--wide { grid-column: 1 / -1; }
.field { display: grid; gap: var(--space-1); min-width: 0; }
/* The custom payment terms field appears only when Custom is chosen.
   CSS only: this product loads no script, and a field the HTML marked
   required while hiding it would stop every save in a browser without
   :has(). The form is what requires the wording. */
.terms-choice:not(:has(option[value="custom"]:checked)) .field--custom-terms { display: none; }

/* A text control fills its column; a checkbox does NOT - left in this rule
   it stretches to the column width and the label ends up half a screen
   away from the box it belongs to. Found on the running dummy at the
   first checkpoint, where a 466px checkbox was sitting beside "Cliente". */
.field input:not([type="checkbox"]):not([type="radio"]),
.field select, .field textarea { max-width: none; width: 100%; }
.field__legend { display: block; font-weight: 600; margin-bottom: var(--space-1); }
.field__error { display: block; color: var(--refusal); font-size: 0.8125rem; font-weight: 600; }
.field__error::before { content: "! "; }

.group { border: 1px solid var(--rule-22); border-radius: var(--r-md); padding: var(--space-4) var(--space-5) var(--space-5); margin: 0 0 var(--space-5); }
.group > legend { font-weight: 700; font-size: 1.0625rem; padding: 0 var(--space-2); }

/* A checkbox keeps a native-sized box inside a full-sized target (owner's
   precision at Checkpoint 1). `.check` IS the label and wraps the input, so
   the whole 44px row activates the control - which is what a labelled
   checkbox's target actually is. The box itself returns to 20px and is the one
   control allowed out of the global 44px floor, because it is the one control
   with a label standing in for it; tests/test_87_checkbox_target.py polices
   that exemption so it cannot spread. */
.check { display: flex; align-items: center; gap: var(--space-2); min-height: var(--target-min);
         margin: 0; font-weight: 400; cursor: pointer; padding-right: var(--space-3); }
.check input[type="checkbox"] {
  width: 20px; height: 20px; min-width: unset; min-height: unset;
  margin: 0; accent-color: var(--structure); cursor: pointer;
}

/* The filter row above a table. A GET, so a reload keeps what was asked for. */
.toolbar { display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-3); margin: 0 0 var(--space-5); }
.toolbar .field { min-width: 16rem; }
.toolbar .btn { margin: 0; }

@media (max-width: 699px) {
  .form-grid { grid-template-columns: minmax(0, 1fr); }
  .toolbar .field { min-width: 0; width: 100%; }
}

/* --- Tabs ----------------------------------------------------------------
   DESIGN.md's `tabs`: 44px text tabs with a 3px structure underline on the
   current one, wrapping rather than scrolling. The current tab carries
   `aria-current`, so the state reads with colour removed. */
.tabs { display: flex; flex-wrap: wrap; gap: var(--space-4); margin: 0 0 var(--space-5); border-bottom: 1px solid var(--rule-22); }
.tabs a { display: inline-flex; align-items: center; min-height: var(--target-min); padding: 0 var(--space-1); color: var(--quiet); font-weight: 600; text-decoration: none; border-bottom: 3px solid transparent; margin-bottom: -1px; }
.tabs a:hover { color: var(--ink); }
.tabs a[aria-current="page"] { color: var(--structure); border-bottom-color: var(--structure); }

/* --- The company's logo ---------------------------------------------------
   Shown at the size a document would use it, bounded so an oversized upload
   cannot push the page sideways. No cropping and no scaling up: what a person
   uploaded is what they see, which is the point of showing it at all. */
.logo { display: block; max-width: 280px; max-height: 120px; width: auto; height: auto; }

/* --- Stepper --------------------------------------------------------------
   DESIGN.md's `stepper`: the states a record passes through, with the current
   one marked. The mark is a WORD plus weight plus a rule, never colour alone -
   `aria-current="step"` carries it to a screen reader and the border carries
   it to a person who cannot see the hue.

   The list has three steps or four depending on what the record is: a direct
   delivery never reserves anything, and showing it a Reserved step would be
   showing a person something they can never do. That is the template's
   decision; this only paints whatever it is given. */
.stepper { display: flex; flex-wrap: wrap; gap: var(--space-2); list-style: none; margin: 0 0 var(--space-5); padding: 0; }
.stepper__step { display: inline-flex; align-items: center; min-height: var(--target-min); padding: 0 var(--space-3); border: 1px solid var(--rule-22); border-radius: var(--r-pill); color: var(--quiet); font-size: 0.8125rem; font-weight: 600; background: var(--surface); }
.stepper__step.is-current { border-color: var(--structure); color: var(--structure); font-weight: 700; }
.stepper__label { white-space: nowrap; }

/* A table's closing line: the subtotal sits under the column it totals. */
tfoot td { font-weight: 700; border-top: 2px solid var(--rule-22); }

/* --- Numbers in tables ----------------------------------------------------
   DESIGN.md: numeric columns are right-aligned with tabular figures, so digits
   line up down a column and a quantity can be compared at a glance. A large
   standalone figure is NOT tabular, which is why this is scoped to cells. */
th.num, td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ==========================================================================
   UX-4 - Operación guiada. The owner approved the proposal on 2026-09-22 and
   these are the pieces it needs that the direction had not drawn yet: Home's
   reading and its decisions, the guided New shipment, the shipment workspace
   and the blocks it folds. Ported from `.impeccable/mocks/ux-4/proposal.css`,
   which was itself written on a byte-for-byte copy of this file, so nothing
   above changed to make room for anything below.

   Same eight colours, same tints, same radius scale, same two shadows, same
   44px rule, no script and no dark surface. Every reveal is CSS `:has()`, as
   the Custom payment terms field already was.
   ========================================================================== */

/* --- Home: the reading of the day ---------------------------------------- */

.brief { display: grid; gap: var(--space-2); }
.brief p { font-size: 1.1875rem; line-height: 1.5; max-width: 60ch; letter-spacing: -0.005em; }
.brief p b { font-weight: 700; }
.brief p a { color: var(--structure); text-decoration-thickness: 1px; text-underline-offset: 3px; }
.brief .sub { max-width: 62ch; }

/* The attention list: one row per thing, the object linked, the reason in
   Quiet Slate, the way to resolve it at the right. */
.card--hero .card__head h2 { font-size: 1.25rem; }
.card--hero .card__body { padding: var(--space-3) var(--space-5) var(--space-5); }
.att { list-style: none; margin: 0; padding: 0; }
.att li { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: var(--space-3) var(--space-5); align-items: center; padding: var(--space-4) 0; border-top: 1px solid var(--rule-22); }
.att li:first-child { border-top: 0; padding-top: 0; }
.att li:last-child { padding-bottom: 0; }
.att svg.i { color: var(--structure); }
.att li[data-kind="missing"] svg.i, .att li[data-kind="stopped"] svg.i { color: var(--refusal); }
.att__text { display: grid; gap: 2px; min-width: 0; }
.att__text b { font-weight: 700; font-size: 1rem; line-height: 1.45; }
.att__text b a { color: var(--ink); }
.att__why { color: var(--quiet); font-size: 0.875rem; }
.att .btn { white-space: nowrap; }
@media (max-width: 699px) {
  .att li { grid-template-columns: 26px minmax(0, 1fr); }
  .att li > .btn { grid-column: 2; justify-self: start; }
}

/* The rest in progress: one line each, one next step each. */
.rest { list-style: none; margin: var(--space-4) 0 0; padding: 0; }
.rest li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-1) var(--space-3); align-items: center; padding: var(--space-3) 0; border-top: 1px solid var(--rule-22); }
.rest li:last-child { padding-bottom: 0; }
.rest__id { min-width: 0; }
.rest__state { display: inline-flex; align-items: center; white-space: nowrap; justify-self: end; }
.rest__what { min-width: 0; }
.rest li > .btn { justify-self: end; white-space: nowrap; }
@media (max-width: 599px) {
  .rest li { grid-template-columns: minmax(0, 1fr); }
  .rest__state, .rest li > .btn { justify-self: start; }
}

/* The spread of the active shipments by state, one bar, every segment named. */
.spread { display: grid; gap: var(--space-2); }
/* Drawn as SVG with width ATTRIBUTES, not inline style: the product's screens
   carry no style attribute, and a rect's width is data. */
.spread__bar { display: block; width: 100%; height: 18px; border-radius: 6px; overflow: hidden; background: var(--rule-22); }
.spread__bar .s-draft { fill: var(--rule-35); }
.spread__bar .s-reserved { fill: var(--structure-16); stroke: var(--structure); stroke-width: 1; vector-effect: non-scaling-stroke; }
.spread__bar .s-ready { fill: var(--structure); }
.spread__legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); font-size: 0.8125rem; color: var(--quiet); margin: 0; padding: 0; list-style: none; }
.spread__legend i { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; }
.spread__legend b { color: var(--ink); }

/* The mini stepper inside a table row: the same states as the page's
   stepper, drawn small, and always beside the state's word. */
.msteps { display: inline-flex; gap: 3px; vertical-align: middle; margin-left: var(--space-2); }
.msteps i { width: 12px; height: 6px; border-radius: 3px; background: var(--rule-22); }
.msteps i.done { background: var(--structure); }
.msteps i.now { background: var(--structure); outline: 2px solid var(--structure-16); }

/* A document's condition as a chip inside a cell: word first, colour second. */
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 1px 8px; border-radius: var(--r-pill); font-size: 0.75rem; font-weight: 700; white-space: nowrap; background: var(--ink-06); color: var(--quiet); }
.chip svg.i { width: 14px; height: 14px; }
.chip--ok { background: var(--structure-10); color: var(--structure); }
.chip--missing { background: var(--refusal-10); color: var(--refusal); }
.chip--draft { background: var(--action-18); color: var(--ink); }
.chips { display: grid; gap: 4px; justify-items: start; }

/* A row that opens a record: the whole row is the link's target area. */
tr.link { cursor: pointer; }
tr.link:hover td { background: rgba(27, 77, 143, 0.04); }
td .stopped { color: var(--refusal); font-weight: 700; font-size: 0.8125rem; display: block; }

/* --- Home: stock by facility ------------------------------------------- */

.facilities { list-style: none; margin: 0; padding: 0; display: grid; }
.facility { display: grid; gap: var(--space-3); padding: var(--space-4) 0; border-top: 1px solid var(--rule-22); }
.facility:first-child { border-top: 0; padding-top: var(--space-1); }
.facility:last-child { padding-bottom: 0; }
.facility__name { display: grid; gap: 2px; }
.facility__name b { font-size: 1rem; letter-spacing: -0.01em; }
.facility__name b a { color: var(--ink); text-decoration: none; }
.facility__name b a:hover { color: var(--structure); text-decoration: underline; }
.facility__name .sub { font-size: 0.8125rem; }
.facility__units { display: grid; gap: var(--space-3); }
.unit { display: grid; gap: 6px; }
.unit__row { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); font-size: 0.875rem; }
.unit__row > span { white-space: nowrap; }
.unit__row .sub { display: inline; }
.unit__row b { font-size: 1.125rem; font-variant-numeric: tabular-nums; }
.facility code, .crumbs code { white-space: nowrap; }
.unitbar { display: block; width: 100%; height: 12px; border-radius: 4px; overflow: hidden; background: var(--rule-22); }

/* The week's comparison. Three figures in ONE currency over ONE week, so the
   lengths are comparable and the chart earns its place. One colour on
   purpose: Marine Blue is structure, and a second hue here would invent a
   meaning the palette reserves for action and refusal. */
.weekbars { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-2) var(--space-4); align-items: center; margin: 0; }
.weekbars dt { font-size: 0.875rem; font-weight: 600; color: var(--quiet); }
.weekbars dd { display: grid; grid-template-columns: minmax(0, 1fr) max-content; gap: var(--space-3); align-items: center; margin: 0; }
.weekbars b { font-variant-numeric: tabular-nums; white-space: nowrap; }
.weekbar { display: block; width: 100%; height: 10px; border-radius: 4px; overflow: hidden; background: var(--rule-22); }
.weekbar .w-part { fill: var(--structure); }

/* The week's headline figures. They carry the screen, so they are read at a
   glance rather than at body size. */
.weekfig { font-size: 1.375rem; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }

/* A figure read DOWN: revenue, cost, margin, credits, and what is left. Two
   columns, so no width clips the last line - which is what a seven-column
   table did to the figure that matters most. */
/* Two columns, so the 46rem minimum every wide table carries would be a
   horizontal scroll for nothing. */
.figsum { width: 100%; min-width: 0; }
/* A subtotal is marked by WEIGHT, not by a rule: under `border-collapse`
   a top border here collapses against the row above and resolves to
   nothing, which is a class that looks like it does something and does not. */
.figsum .figsum__sum th { color: var(--ink); }
.figsum .figsum__sum td { font-weight: 700; }
.unitbar .u-avail { fill: var(--structure); }
.unitbar .u-res { fill: var(--structure-16); stroke: var(--structure); stroke-width: 1; vector-effect: non-scaling-stroke; }

/* --- Two-column rows ------------------------------------------------------ */

.cols { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: var(--space-5); align-items: start; }
.cols--even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cols--home { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
.cols > * { min-width: 0; }
.stack { display: grid; gap: var(--space-5); }
.stack > * { min-width: 0; }
.push { margin-left: auto; }
.mt-3 { margin-top: var(--space-3); }
.section-title { margin-top: 0; }
@media (max-width: 1199px) { .cols { grid-template-columns: minmax(0, 1fr); } }

/* --- New shipment: the guided form --------------------------------------- */

.wiz { display: grid; gap: var(--space-5); }
.step { display: grid; gap: var(--space-3); }
.step > h2 { margin: 0; }
fieldset.step { border: 0; padding: 0; margin: 0; min-width: 0; }
.step > legend { padding: 0; margin: 0 0 var(--space-3); font-size: 1.0625rem; font-weight: 700; letter-spacing: -0.01em; }
fieldset.field--group { border: 0; padding: 0; margin: 0; min-width: 0; }
.field--group > legend { padding: 0; }
.step .lead { color: var(--quiet); font-size: 0.9375rem; max-width: 62ch; }
.choices2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
@media (max-width: 699px) { .choices2 { grid-template-columns: minmax(0, 1fr); } }
.choice { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-3); align-items: start; padding: var(--space-4) var(--space-4) var(--space-4) var(--space-3); border: 1px solid var(--rule-35); border-radius: var(--r-md); background: var(--field); cursor: pointer; font-weight: 400; margin: 0; min-height: var(--target-min); }
.choice input[type="radio"] { width: 20px; height: 20px; min-width: unset; min-height: unset; margin: 3px 0 0; accent-color: var(--structure); cursor: pointer; }
.choice__text { display: grid; gap: 2px; }
.choice__text b { font-size: 1rem; }
.choice__text span { color: var(--quiet); font-size: 0.875rem; }
.choice:hover { background: var(--ground); }
.choice:has(input:checked) { border: 2px solid var(--structure); padding: calc(var(--space-4) - 1px) calc(var(--space-4) - 1px) calc(var(--space-4) - 1px) calc(var(--space-3) - 1px); background: var(--structure-10); }
.choice:has(input:focus-visible) { outline: 3px solid var(--structure); outline-offset: 2px; }
/* What follows an answer appears only for that answer. CSS alone, as the
   Custom payment terms field already does; no screen loads a script.

   The selectors name the VALUE rather than an id, because the ids are
   Django's and would change with the widget. Block pieces use `only-*`;
   words inside a sentence use `if-*`. Both branches stay in the page, so a
   person can change their mind - and the form refuses, with a sentence, a
   value posted for the branch the answer hides. */
.only-cold, .only-direct, .only-pickup, .only-llc,
.if-cold, .if-direct { display: none; }
.wiz:has([name="inventory_handling"][value="from_inventory"]:checked) .only-cold,
.wiz:has([name="inventory_handling"][value="direct_delivery"]:checked) .only-direct,
.wiz:has([name="delivery_method"][value="customer_pickup"]:checked) .only-pickup,
.wiz:has([name="delivery_method"][value="llc_arranged_delivery"]:checked) .only-llc {
  display: grid; gap: var(--space-3);
}
.wiz:has([name="inventory_handling"][value="from_inventory"]:checked) .if-cold,
.wiz:has([name="inventory_handling"][value="direct_delivery"]:checked) .if-direct { display: inline; }
.wiz:has([name="inventory_handling"][value="from_inventory"]:checked) li.if-cold,
.wiz:has([name="inventory_handling"][value="direct_delivery"]:checked) li.if-direct { display: list-item; }
/* A shipment that already has lines has its handling settled, so the form
   does not render the question. Everything that depends on the answer then
   belongs to the shipment's own mode, which the page states in words. */
.wiz:not(:has([name="inventory_handling"])) .only-cold,
.wiz:not(:has([name="inventory_handling"])) .only-direct { display: grid; gap: var(--space-3); }
.wiz .field { max-width: 34rem; }
.wiz .field select, .wiz .field input { max-width: 34rem; }
.wiz .fold > summary { padding-left: 0; }
.wiz .fold .form-grid { margin-top: var(--space-3); }
.hint { display: flex; gap: var(--space-2); align-items: flex-start; color: var(--quiet); font-size: 0.875rem; max-width: 62ch; }
.hint svg.i { color: var(--structure); flex: none; margin-top: 2px; }
.hint--warn svg.i { color: var(--ink); }

/* What you are creating: the sentence the answers add up to. */
.sum { position: sticky; top: calc(var(--header) + var(--space-5)); }
.sum p { font-size: 1rem; }
.sum ol { margin: var(--space-3) 0 0; padding-left: 1.25rem; color: var(--quiet); font-size: 0.875rem; display: grid; gap: 4px; }
.sum ol b { color: var(--ink); }
/* A stock hint inside a select's option is not possible; the availability a
   facility holds is said beside the control instead. */
.avail { display: block; font-size: 0.875rem; color: var(--quiet); line-height: 1.6; max-width: 62ch; }
.avail b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* The lot picker: one radio row per lot, its availability at THIS facility
   beside it, so nobody reads a UUID to choose. */
.lots { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.lots label { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-3); align-items: center; padding: var(--space-2) var(--space-3); border: 1px solid var(--rule-35); border-radius: 10px; margin: 0; font-weight: 400; min-height: var(--target-min); cursor: pointer; }
.lots label:has(input:checked) { border: 2px solid var(--structure); background: var(--structure-10); padding: calc(var(--space-2) - 1px) calc(var(--space-3) - 1px); }
.lots input[type="radio"] { width: 20px; height: 20px; min-width: unset; min-height: unset; margin: 0; accent-color: var(--structure); }
.lots .lot__code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.92em; }
.lots .lot__meta { color: var(--quiet); font-size: 0.8125rem; display: block; }
.lots .lot__avail { text-align: right; font-variant-numeric: tabular-nums; font-size: 0.875rem; }
.lots .lot__avail b { display: block; font-size: 1rem; }
.qty { display: flex; align-items: center; gap: var(--space-2); }
.qty input { max-width: 12rem; }
.qty .unitword { font-weight: 600; color: var(--quiet); }

/* --- Shipment detail: the workspace -------------------------------------- */

.crumbs { display: flex; flex-wrap: wrap; gap: var(--space-2); font-size: 0.8125rem; color: var(--quiet); margin: 0; padding: 0; list-style: none; }
.crumbs a { color: var(--structure); text-decoration: none; }
.crumbs li + li::before { content: "/"; margin-right: var(--space-2); color: var(--rule); }
.shiphead { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-3) var(--space-4); }
.shiphead__text { display: grid; gap: var(--space-1); margin-right: auto; min-width: 0; }
.shiphead h1 { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin: 0; }
.shiphead .meaning { color: var(--quiet); max-width: 62ch; }
.shiphead .meaning b { color: var(--ink); font-weight: 600; }

/* "What is next": the states, what is still owed, and the one action. */
.next { display: grid; gap: var(--space-4); }
.next .stepper { margin: 0; }
.todo { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.todo li { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: var(--space-2); align-items: start; font-size: 0.9375rem; }
.todo svg.i { width: 20px; height: 20px; }
.todo li[data-done="yes"] svg.i { color: var(--structure); }
.todo li[data-done="no"] svg.i { color: var(--refusal); }
.todo li[data-done="no"] b { color: var(--refusal); }
.todo li[data-done="pending"] svg.i { color: var(--structure); }
.todo li[data-done="pending"] b { color: var(--ink); }
.todo .sub { font-size: 0.8125rem; }
.next .actions .btn-primary { min-width: 14rem; }
/* The pause before an irreversible step: a disclosure whose summary is the
   primary button; open, the summary steps back to white so the page still
   carries one yellow control, the definitive one. No script. */
.confirm > summary { list-style: none; display: inline-flex; min-width: 14rem; }
.confirm > summary::-webkit-details-marker { display: none; }
.confirm[open] > summary { background: var(--field); border-color: var(--rule-35); box-shadow: none; }
.confirm__body { margin-top: var(--space-3); padding: var(--space-3) var(--space-4); border: 1px solid var(--rule-35); border-radius: 10px; display: grid; gap: var(--space-3); max-width: 62ch; }
.confirm__body p { font-size: 0.9375rem; }
/* The stepper's past: filled, with a check, and the word "done" for a reader. */
.stepper__step.is-done { color: var(--structure); border-color: var(--structure-16); background: var(--structure-10); gap: 6px; }

/* One document, one row: name, number and version, what it froze, and its
   controls. Its options fold beneath it, and only the invoice has any. */
.docrow { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); align-items: start; padding: var(--space-4) 0; border-top: 1px solid var(--rule-22); }
.docrow:first-child { border-top: 0; padding-top: 0; }
.docrow:last-child { padding-bottom: 0; }
.docrow__text { display: grid; gap: 4px; min-width: 0; }
.docrow__text .name { font-weight: 700; font-size: 1rem; display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.docrow__text .frozen { color: var(--quiet); font-size: 0.875rem; }
.docrow__text .frozen b { color: var(--ink); font-weight: 600; }
.docrow .actions { justify-content: flex-start; }
.docrow .fold { grid-column: 1 / -1; }
form.docrow { margin: 0; }
.docrow .fold > summary { font-size: 0.875rem; padding-left: 0; }
.docrow .fold .form-grid { margin: var(--space-2) 0 var(--space-3); }
.docrow .versions { margin: 0; padding: 0; list-style: none; font-size: 0.8125rem; color: var(--quiet); display: grid; gap: 2px; }
.docrow .versions code { color: var(--ink); }

/* Origin and destination, side by side, each block a place with its role. */
.places { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
.place { display: grid; align-content: start; gap: 4px; padding: var(--space-3) var(--space-4); border: 1px solid var(--rule-22); border-radius: 10px; font-size: 0.9375rem; }
.place .role { font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--quiet); }
.place b { font-weight: 700; }
.place .sub { font-size: 0.875rem; }
.place .place__note { font-size: 0.8125rem; color: var(--quiet); margin-top: 4px; }
@media (max-width: 699px) { .places { grid-template-columns: minmax(0, 1fr); } }

/* The record's history: real events only, with who and when. */
.timeline { list-style: none; margin: 0; padding: 0 0 0 var(--space-4); border-left: 2px solid var(--rule-22); display: grid; gap: var(--space-3); }
.timeline li { position: relative; display: grid; gap: 2px; font-size: 0.9375rem; }
.timeline li::before { content: ""; position: absolute; left: calc(-1 * var(--space-4) - 6px); top: 7px; width: 10px; height: 10px; border-radius: 50%; background: var(--structure); }
.timeline .when { font-size: 0.8125rem; color: var(--quiet); }
.timeline li[data-future="yes"]::before { background: var(--field); border: 2px solid var(--rule-35); }
.timeline li[data-future="yes"] { color: var(--quiet); }

.sum .kv { font-size: 0.9375rem; grid-template-columns: minmax(7rem, 9rem) minmax(0, 1fr); }

.folds { display: grid; gap: var(--space-3); }
.foldcard > summary {
  display: list-item; list-style-position: inside;
  min-height: var(--target-min); padding: var(--space-3) var(--space-5);
  cursor: pointer; border-radius: var(--r-md);
}
.foldcard > summary:hover { background: var(--ground); }
.foldcard[open] > summary { border-bottom: 1px solid var(--rule-22); border-radius: var(--r-md) var(--r-md) 0 0; }
.foldcard__title { font-weight: 700; font-size: 1.0625rem; letter-spacing: -0.01em; }
/* Its state travels in the same line, so folding hides detail, never presence. */
.foldcard__state { color: var(--quiet); font-size: 0.875rem; }
.foldcard__state::before { content: "·"; margin: 0 8px; }
/* Cancel is last and set apart by space, not by colour: oxide marks a hold. */
.foldcard.danger { margin-top: var(--space-2); }

/* Money is present on the screen and absent from the Packing List, as the
   product already does; the table just needs its footer. */
.lines tfoot td { font-weight: 700; }
table.fit { min-width: 40rem; }
.lines td .sub { white-space: normal; }
.lines td.num .sub { text-align: right; font-variant-numeric: tabular-nums; }


/* Small utilities the pages use instead of inline styles. */
.sub--inline { display: inline; font-weight: 400; }
.plain-list { margin: 0; padding-left: 1.25rem; display: grid; gap: var(--space-2); }
.app--door .content.content--narrow { max-width: 64rem; margin: 0 auto; }
.content--wide { max-width: none; }
.spread__legend .s-draft { background: var(--rule-35); }
.spread__legend .s-reserved { background: var(--structure-16); border: 1px solid var(--structure); box-sizing: border-box; }
.spread__legend .s-ready { background: var(--structure); }

/* Prose inside a card keeps a readable measure. */
.card__body > p.sub, .card__body > p { max-width: 72ch; }

/* --- Below 900px a table row becomes a stacked record -------------------
   Nothing is hidden and nothing scrolls inside the card: the id and its
   sub-line first, then each cell with the column's name before it, then the
   row's action at full width. The thead stays for assistive technology. */
@media (max-width: 899px) {
  table.fit { min-width: 0; }
  table.fit thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  table.fit, table.fit tbody, table.fit tfoot, table.fit tr, table.fit td { display: block; }
  table.fit tbody tr { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--rule-22); }
  table.fit tbody tr:last-child { border-bottom: 0; }
  table.fit td { border: 0; padding: 2px 0; }
  table.fit td.num { text-align: left; white-space: normal; }
  table.fit td .sub { display: inline; margin-left: var(--space-1); }
  table.fit td[data-label]::before { content: attr(data-label) ": "; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--quiet); margin-right: 4px; }
  table.fit td.cell-action { padding-top: var(--space-2); }
  table.fit td.cell-action .btn { width: 100%; }
  table.fit tfoot td { border-top: 2px solid var(--rule-22); padding: var(--space-3) var(--space-4); display: flex; justify-content: space-between; }
  table.fit tfoot td:empty { display: none; }
  table.fit .chips { display: inline-grid; vertical-align: top; }
  table.fit .msteps { margin-left: var(--space-2); }
}

/* Home's rhythm: the reading breathes before the decisions begin. */
.pagehead + .card--hero { margin-top: var(--space-2); }
