:root {
  --navy: #14213d;
  --navy-soft: #22304f;
  --ink: #1b1f28;
  --muted: #5d6675;
  --line: #dfe3ea;
  --bg: #f6f7f9;
  --card: #ffffff;
  --accent: #1f5f8b;
  --flag: #9a3412;
  --ok: #14653a;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

body.centered {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 28px;
  width: 100%;
  max-width: 380px;
  box-shadow: 0 1px 2px rgba(20, 33, 61, .06);
}
.card.wide { max-width: none; margin-bottom: 20px; }

.wordmark {
  margin: 0;
  font-size: 22px;
  font-weight: 650;
  letter-spacing: -.01em;
  color: var(--navy);
}
.wordmark span { font-weight: 400; color: var(--muted); }
.wordmark.small { font-size: 16px; }

.sub { margin: 4px 0 22px; color: var(--muted); font-size: 13px; }

label {
  display: block;
  margin: 14px 0 5px;
  font-size: 13px;
  font-weight: 600;
  color: var(--navy-soft);
}

input {
  width: 100%;
  padding: 9px 11px;
  font: inherit;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fff;
  color: var(--ink);
}
input:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }

button {
  margin-top: 20px;
  width: 100%;
  padding: 10px;
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--navy);
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
button:hover { background: var(--navy-soft); }
button[disabled] { opacity: .55; cursor: default; }

button.link {
  width: auto;
  margin: 0;
  padding: 0;
  background: none;
  color: var(--accent);
  font-weight: 500;
  text-decoration: underline;
}
button.link:hover { background: none; color: var(--navy); }

.error {
  margin: 14px 0 0;
  padding: 9px 11px;
  background: #fdf2f0;
  border: 1px solid #f0c8c0;
  border-radius: 6px;
  color: var(--flag);
  font-size: 13px;
}

.fineprint {
  margin: 22px 0 0;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.45;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 12px 22px;
  background: #fff;
  border-bottom: 1px solid var(--line);
}
.tabs { display: flex; gap: 4px; flex: 1; }
.tab {
  padding: 6px 11px;
  border-radius: 6px;
  font-size: 14px;
  color: var(--muted);
  text-decoration: none;
}
.tab.current { background: var(--bg); color: var(--navy); font-weight: 600; }
.tab.disabled { opacity: .4; pointer-events: none; }
.who { margin-left: auto; display: flex; gap: 14px; align-items: center; font-size: 13px; color: var(--muted); }

.wrap { max-width: 900px; margin: 24px auto; padding: 0 22px; }

h2 { margin: 0 0 10px; font-size: 16px; color: var(--navy); }

.status { display: grid; grid-template-columns: max-content 1fr; gap: 6px 18px; margin: 16px 0 0; font-size: 13px; }
.status dt { color: var(--muted); }
.status dd { margin: 0; font-variant-numeric: tabular-nums; }
.status dd.ok { color: var(--ok); }
.status dd.bad { color: var(--flag); }

.grid { width: 100%; border-collapse: collapse; font-size: 13px; }
.grid td { padding: 7px 10px; border-top: 1px solid var(--line); }
.grid tr:first-child td { border-top: 0; }
.grid .muted { color: var(--muted); }

/* ── intake ─────────────────────────────────────────────────────────────── */

.wide-wrap { max-width: 1040px; }

.hint { margin: 0 0 16px; color: var(--muted); font-size: 13px; }
.hint.small { font-size: 12px; margin: 8px 0 0; }
.opt { color: var(--muted); font-weight: 400; font-size: 11px; }

.dropzone {
  border: 2px dashed var(--line);
  border-radius: 10px;
  background: #fbfcfd;
  padding: 34px 20px;
  text-align: center;
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.dropzone:hover { border-color: var(--accent); background: #f7fafc; }
.dropzone:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dropzone.over { border-color: var(--accent); background: #eef6fb; border-style: solid; }

.dz-main { margin: 0 0 6px; font-size: 15px; font-weight: 600; color: var(--navy); }
.dz-or { margin: 0 0 10px; font-size: 13px; color: var(--muted); }
.dz-note { margin: 0; font-size: 12px; color: var(--muted); }
kbd {
  font: inherit; font-size: 11px; padding: 1px 5px;
  border: 1px solid var(--line); border-radius: 4px; background: #fff;
}

.outlook-note {
  margin: 14px 0 0; padding: 10px 12px;
  background: #fffbeb; border: 1px solid #f2e2b8; border-radius: 8px;
  font-size: 13px;
}
.outlook-note summary { cursor: pointer; font-weight: 600; color: #7a5a10; }
.outlook-note p { margin: 10px 0 0; color: #6b5514; line-height: 1.5; }

.staged { margin-top: 18px; }
.staged th {
  text-align: left; font-size: 11px; text-transform: uppercase;
  letter-spacing: .04em; color: var(--muted); padding: 0 10px 6px; font-weight: 600;
}
.staged th.num, .grid td.num { text-align: right; }
.staged-summary { margin: 10px 0 0; font-size: 12px; color: var(--muted); }

.grid td.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.grid select {
  font: inherit; font-size: 12px; padding: 3px 6px;
  border: 1px solid var(--line); border-radius: 5px; background: #fff; color: var(--ink);
}
.grid a { color: var(--accent); }

/* ── audit log ───────────────────────────────────────────────────────────── */

/*
 * THE DETAIL COLUMN RAN OFF THE CARD, and no amount of truncating fixed it: the
 * text is truncated at 160 characters already, and a UUID offers no break
 * opportunity, so a single id is wider than the space and pushed the table past
 * the card. Measured at a 1280 viewport: page scrollWidth 1352, card 1134,
 * table 1252, widest cell 591.
 *
 * Two rules, and both are needed. `table-layout: fixed` stops the detail column
 * claiming width from its content; `overflow-wrap: anywhere` lets a UUID break
 * mid-token, which is the only way a 36-character word with no hyphen or space
 * fits a narrow column.
 *
 * The horizontal scroll is on a WRAPPER rather than the page. Wide content
 * scrolls inside its own container; the page body must never scroll sideways,
 * because that moves the navigation off screen to read a table cell.
 */
/* The package title is an <h2> rather than a pagehead, so the link needs its
 * own spacing instead of the `.crumb` gap a flex row supplies. */
.history-link { margin-left: 12px; font-size: 13px; font-weight: 400; }

.audit-scroll { overflow-x: auto; }
.audit-log { table-layout: fixed; min-width: 900px; }
.audit-log th, .audit-log td { vertical-align: top; }
.audit-log .detail { overflow-wrap: anywhere; word-break: break-word; }
/* The sentence reads as the account; the stored keys under it read as
 * corroboration. Not bold: it is a description, not a heading. */
.audit-log .says { color: var(--ink); }
.audit-log col.c-when   { width: 150px; }
.audit-log col.c-who    { width: 120px; }
.audit-log col.c-action { width: 190px; }
.audit-log col.c-entity { width: 190px; }

.fields { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 22px; }
.field { flex: 1 1 240px; }
.field.narrow { flex: 0 0 170px; }
.field label { margin-top: 0; }

.actions { display: flex; align-items: center; gap: 18px; margin-top: 20px; }
.actions button:not(.link) { width: auto; margin: 0; padding: 9px 20px; }

.progress { margin-top: 18px; display: grid; gap: 7px; }
.prow { display: grid; grid-template-columns: minmax(0, 1fr) 130px 150px; gap: 12px; align-items: center; font-size: 12px; }
.pname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pbar { height: 5px; background: var(--line); border-radius: 3px; overflow: hidden; }
.pfill { display: block; height: 100%; width: 0; background: var(--accent); transition: width .15s; }
.pstate { color: var(--muted); }
.pstate.ok { color: var(--ok); }
.pstate.bad { color: var(--flag); }

/* ── records, demos, people ─────────────────────────────────────────────── */

.wrap.roomy { max-width: 1180px; }

.pagehead { display: flex; align-items: baseline; gap: 16px; margin: 0 0 18px; flex-wrap: wrap; }
.pagehead h1 { margin: 0; font-size: 21px; color: var(--navy); font-weight: 650; letter-spacing: -.01em; }
.pagehead .crumb { font-size: 13px; color: var(--muted); }
.pagehead .crumb a { color: var(--accent); }
.pagehead .spacer { flex: 1; }

.toolbar { display: flex; gap: 10px; align-items: center; margin: 0 0 14px; flex-wrap: wrap; }
.toolbar input[type="search"] { width: 260px; padding: 7px 10px; }
.toolbar button:not(.link) { width: auto; margin: 0; padding: 7px 15px; font-size: 13px; }

.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
.cols.wide-left { grid-template-columns: 1.45fr 1fr; }
@media (max-width: 900px) { .cols, .cols.wide-left { grid-template-columns: 1fr; } }

.card h3 { margin: 0 0 10px; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 700; }
.card + .card { margin-top: 0; }
.card.wide + .card.wide { margin-top: 20px; }

/* A sortable header says so, and says which way. Nothing sorts silently. */
.grid th.sortable { cursor: pointer; user-select: none; }
.grid th.sortable:hover { color: var(--ink); }
.grid th.sorted { color: var(--ink); }
.sortmark { font-weight: 700; }
.grid th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); padding: 0 10px 6px; font-weight: 600;
}
.grid tbody tr:hover { background: #fbfcfd; }
.grid td.tight { width: 1%; white-space: nowrap; }

.pill {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 600; letter-spacing: .01em;
  background: var(--bg); color: var(--muted); border: 1px solid var(--line);
}
.pill.ok { background: #eef7f1; color: var(--ok); border-color: #c6e2d1; }
.pill.warn { background: #fffbeb; color: #7a5a10; border-color: #f2e2b8; }
.pill.flag { background: #fdf2f0; color: var(--flag); border-color: #f0c8c0; }
.pill.info { background: #eef6fb; color: var(--accent); border-color: #cbe0ee; }

.empty { margin: 6px 0; padding: 18px; text-align: center; color: var(--muted); font-size: 13px;
  border: 1px dashed var(--line); border-radius: 8px; background: #fbfcfd; }

.kv { display: grid; grid-template-columns: max-content 1fr; gap: 6px 18px; margin: 0; font-size: 13px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }

.calc { font-size: 13px; }
.calc .line { display: flex; justify-content: space-between; gap: 14px; padding: 5px 0; border-top: 1px solid var(--line); }
.calc .line:first-child { border-top: 0; }
.calc .line b { font-weight: 600; font-variant-numeric: tabular-nums; }
.calc .formula { margin: 10px 0 0; padding: 8px 10px; background: var(--bg); border-radius: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; color: var(--muted); }

.banner { padding: 10px 12px; border-radius: 8px; font-size: 13px; margin: 0 0 14px; }
.banner.warn { background: #fffbeb; border: 1px solid #f2e2b8; color: #6b5514; }
.banner.flag { background: #fdf2f0; border: 1px solid #f0c8c0; color: var(--flag); }
.banner.info { background: #eef6fb; border: 1px solid #cbe0ee; color: #1a4a6b; }
.banner b { font-weight: 650; }

.rowform { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; margin-top: 14px;
  padding-top: 14px; border-top: 1px solid var(--line); }
.rowform .field { flex: 1 1 150px; }
.rowform .field label { margin-top: 0; }
.rowform button:not(.link) { width: auto; margin: 0; padding: 8px 16px; font-size: 13px; }
.rowform select, .rowform input { width: 100%; padding: 7px 9px; font: inherit; font-size: 13px;
  border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--ink); }
.rowform textarea { width: 100%; padding: 7px 9px; font: inherit; font-size: 13px;
  border: 1px solid var(--line); border-radius: 6px; resize: vertical; min-height: 60px; }

.notice {
  position: fixed; left: 50%; bottom: 22px; transform: translate(-50%, 130%);
  max-width: 560px; padding: 11px 16px; border-radius: 8px; font-size: 13px;
  background: var(--navy); color: #fff; box-shadow: 0 6px 20px rgba(20,33,61,.22);
  transition: transform .18s ease; z-index: 50;
}
.notice.shown { transform: translate(-50%, 0); }
.notice.error { background: #7f2418; }
.notice.ok { background: #14653a; }

.seg { border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; margin-top: 8px; background: #fff; }
.seg.unclassified { border-style: dashed; background: #fbfcfd; }
/* Red: a human should look at this. Green: one has. Neither is a finding --
   nothing here says a package falls short of a standard. The left border
   carries the state so it reads down a list of sixteen without shouting. */
.seg.flagged { border-left: 3px solid var(--flag); background: #fdf7f6; }
.seg.checked { border-left: 3px solid var(--ok); }
/* Neutral: the platform has no reader for this type yet. Deliberately not red
   and not green -- it reports a state of the platform, not a job for a person
   and not something anyone has confirmed. */
.seg.noreader { border-left: 3px solid var(--line); }
.flagbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.parse-fields tr.checked td { background: #f4fbf6; }
.parse-fields tr.flagged td { background: #fdf7f6; }
.parse-fields td.checkcell { width: 1%; white-space: nowrap; text-align: right; }
.parse-fields td.checkcell .link { font-size: 11px; }
.parse-fields tr .checkcell .link { visibility: hidden; }
.parse-fields tr:hover .checkcell .link { visibility: visible; }
.parse-fields tr.checked .checkcell .link { visibility: visible; }
/* A plain moving count. No bar, no spinner, no estimate: three timings is not
   enough to predict from, and a timer that says two minutes and takes four is
   worse than no timer. */
.parse-progress { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 10px 0; }
.seg-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.seg-pages { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; color: var(--muted); }
.seg-actions { margin-left: auto; display: flex; gap: 10px; align-items: center; }
.seg select { font: inherit; font-size: 12px; padding: 3px 6px; border: 1px solid var(--line);
  border-radius: 5px; background: #fff; }
.seg .hash { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: var(--muted); }

.fineprint.sticky { margin-top: 28px; }

/* Utility classes rather than inline styles: the CSP is `style-src 'self'`
   with no 'unsafe-inline', so a style attribute set from JS is blocked
   outright. Loosening the policy for a handful of margins would be a poor
   trade, so the handful of margins live here instead. */
.btn-inline { width: auto; margin: 0; padding: 7px 15px; font-size: 13px; }
/* ANYTHING ACTING ON A PILL SITS BENEATH THAT PILL. Stacked rather than
   beside, because each action to the right of its pill spent horizontal space
   on every roster row and squeezed the panel next to it. */
.pillstack { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.pillstack > * { margin: 0; }
.pillstack .seg-pages { white-space: normal; max-width: 190px; }

.ml { margin-left: 8px; }
/* `button.link` sets `margin: 0` and outranks `.ml` on specificity (0,1,1
   against 0,1,0), so a link button carrying `ml` got no gap whatever the order
   of these rules. That is why "pages 3-6, 8-11, 14-16" ran straight into "no
   segment needed": a trailing space in the preceding span was doing all the
   work, and it is not enough. Applies to every `link ml` in the app. */
button.link.ml { margin-left: 8px; }

/* The help affordance on a red flag. Small, blue, circled, and never so loud
   that it competes with the flag it explains. */
.helpdot { display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; padding: 0; margin-left: 6px; border-radius: 50%;
  border: 1px solid var(--accent); background: #fff; color: var(--accent);
  font-size: 10px; font-weight: 700; line-height: 1; cursor: pointer;
  vertical-align: middle; flex: none; }
.helpdot:hover { background: var(--accent); color: #fff; }
.helpbox { position: absolute; z-index: 40; margin-top: 6px; max-width: 380px;
  background: #fff; border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 6px 20px rgba(16,32,48,.13); padding: 12px 14px; font-size: 12.5px;
  line-height: 1.45; text-align: left; white-space: normal; font-weight: 400; }
.helpbox-title { font-weight: 650; margin-bottom: 8px; }
.helpbox-h { font-weight: 650; color: var(--accent); margin-top: 8px; font-size: 11px;
  text-transform: uppercase; letter-spacing: .04em; }
.helpbox-h:first-of-type { margin-top: 0; }
.helpbox-p { color: var(--ink); margin-top: 2px; }
.helpbox-close { margin-top: 10px; font-size: 11px; }
.flagbar, .seg-actions, td, .prow-line { position: relative; }
/* One line per file beneath the type-ordered contents table. Coverage is a
   property of a FILE -- page ranges only mean something inside one. */
.prow-line { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding: 5px 0; border-bottom: 1px solid var(--line); font-size: 13px; }
.prow-line:last-child { border-bottom: 0; }
#package-contents { margin-top: 26px; }
#package-contents h3 { margin-bottom: 4px; }
.sublabel { font-size: 12px; color: var(--muted); }
.field.full { flex-basis: 100%; flex-grow: 1; }
.tight-p { margin: 6px 0 0; }
.spaced { margin-top: 20px; }
.spaced-sm { margin-top: 12px; }
.inline-check { display: flex; gap: 6px; align-items: center; margin: 0; font-weight: 400; }
.inline-check input { width: auto; }
.tabrow button { margin: 0; }

/* ── type-to-filter picker ──────────────────────────────────────────────── */
/* A native select cannot be filtered, and these lists reach hundreds of venues
   and thousands of people. Input plus listbox instead. */
.combo { position: relative; }
.combo-input { width: 100%; padding: 7px 9px; font: inherit; font-size: 13px;
  border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--ink); }
/* A PICKER IN A TABLE CELL NEEDS A FLOOR. `.grid td.tight` is `width: 1%`,
   which means "shrink to the content's minimum" -- and the content here is an
   input at `width: 100%`, whose minimum contribution is effectively nothing.
   So the cell collapsed to 40px with a 20px input, clipping "Jumper" to
   invisible, and the grey placeholder with it. Present since the roster was
   built; it became obvious once the row carried enough columns to squeeze.
   The floor tells the table what the control actually needs. */
.grid td .combo { min-width: 110px; }
.combo-input:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.combo-list {
  position: absolute; z-index: 30; top: calc(100% + 3px); left: 0; right: 0;
  max-height: 260px; overflow-y: auto; background: #fff;
  border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 6px 20px rgba(20, 33, 61, .13);
}
.combo-option { padding: 7px 10px; font-size: 13px; cursor: pointer; }
.combo-option:hover, .combo-option.active { background: #eef6fb; }
.combo-option.chosen { font-weight: 600; }
.combo-option.muted { color: var(--muted); }
/* Create-and-select, offered when the typed text matches nothing exactly. */
.combo-option.create { color: var(--accent); font-weight: 600; }
/* TYPED TEXT THAT MATCHED NOTHING. Amber, not red: nothing is wrong yet, the
   operator simply has not finished choosing. Red is reserved for "act on this". */
.combo-input.unresolved { border-color: #d9a441; background: #fffdf6; }
.combo-note { margin: 3px 0 0; font-size: 11px; color: #7a5a10; }

/* A pill that is also a control. The base `button` rule is full width with its
   own chrome and colour; this strips all of it so the pill reads as a pill and
   the only difference from a static one is that it can be pressed. */
button.pill.as-button {
  margin: 0; width: auto; color: inherit; background: inherit;
  border: 1px solid var(--line); cursor: pointer;
}
button.pill.as-button.flag { background: #fdf2f0; color: var(--flag); border-color: #f0c8c0; }
/* A NEUTRAL pill button: the same control with no colour, for a state that
   asks nothing of anyone -- a lookup on a pilot or ground crew member, where
   not being a USPA member is the ordinary case. */
button.pill.as-button:not(.flag) { background: var(--bg); color: var(--muted); }
button.pill.as-button:hover { filter: brightness(0.97); }

/* ── modal ──────────────────────────────────────────────────────────────── */
/* Add forms sat below the list, which works with four rows and means scrolling
   past four hundred. */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: start center;
  padding: 8vh 20px 20px; background: rgba(20, 33, 61, .34);
}
.modal-card {
  width: 100%; max-width: 460px; background: var(--card);
  border-radius: 10px; padding: 24px 26px 22px;
  box-shadow: 0 14px 44px rgba(20, 33, 61, .28);
}
.modal-card h2 { margin: 0 0 16px; }
.modal-body .field { flex: none; margin-bottom: 14px; }
.modal-body .field label { margin-top: 0; }
.modal-body input, .modal-body textarea {
  width: 100%; padding: 8px 10px; font: inherit; font-size: 14px;
  border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--ink);
}
.modal-actions { display: flex; align-items: center; justify-content: flex-end; gap: 18px; margin-top: 20px; }
.modal-actions button:not(.link) { width: auto; margin: 0; padding: 9px 22px; }
.modal-card .error { margin-top: 14px; }

/*
 * A QUESTION WITH ITS EXPLANATION.
 *
 * The explanation scrolls; the question does not. That is the whole point of
 * moving these off `window.prompt`: a native prompt is sized by the browser, so
 * the three dialogs carrying the most important text in the app pushed their
 * question below the fold. Here the field, its hint and the buttons are always
 * visible and only the prose above them moves.
 *
 * `max-height` in vh rather than px, so a short window shrinks the prose
 * instead of pushing the field off the bottom. `40vh` leaves room for the
 * title, the field, the hint and the actions inside the 8vh top padding the
 * backdrop already applies.
 */
.ask-explain {
  max-height: 40vh; overflow-y: auto; margin-bottom: 4px;
  padding-right: 6px; border-bottom: 1px solid var(--line);
}
.ask-explain p { margin: 0 0 12px; font-size: 13px; line-height: 1.55; color: var(--ink); }
.ask-explain p:last-child { margin-bottom: 14px; }

.ask-question label { display: block; margin: 0 0 6px; font-weight: 600; font-size: 13px; }
.ask-hint { margin: 6px 0 0; font-size: 12px; color: var(--muted); }

/* Wider than the add-a-record modals: these carry paragraphs, not four fields. */
.modal-card:has(.ask-explain) { max-width: 560px; }

/* ── label wrapping and spacing ─────────────────────────────────────────── */
/* "Jumpers landing within 30 s" orphaned the lone "s" on its own line. Give
   labels room, and never break a unit off its number. */
label { text-wrap: balance; }
.field { min-width: 190px; }
.field.narrow { flex: 0 0 200px; }
/* TWO FIELDS THAT MUST SHARE ONE LINE, whatever the column gives them.
   `narrow` is a fixed basis with a floor, which is right in a full-width form
   and wrong in the narrow half of a split: two of them demand 416px and the
   column offers 334px, so they wrapped. These split the row instead. */
.fields.pair { flex-wrap: nowrap; }
.fields.pair > .field { flex: 1 1 0; min-width: 0; }
.nowrap { white-space: nowrap; }

/* A button followed by a new section needs clear separation, and section
   headings need consistent space above them. `.card h3` sets margin 0 and out-
   specifies a plain sibling selector, so this has to match at least as tightly. */
.card h3:not(:first-child) { margin-top: 28px; }
.card h3 + .hint { margin-top: -2px; }
.card .actions { margin-bottom: 4px; }

/* Manual segmenting is the fallback whenever extraction cannot read a
   document, so it has to be tolerable. Typing page numbers blind means opening
   the PDF in another window and counting. */
.seg-preview {
  width: 100%; height: 420px; margin-top: 12px;
  border: 1px solid var(--line); border-radius: 8px; background: #fbfcfd;
}

/* Phase 4: raw parse results. Deliberately plain — this shows what was read
   off the page and which route read it, and says nothing about whether any of
   it is right. */
.parse-pane { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.parse-head { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.parse-fields td { font-size: 12px; vertical-align: top; }
.parse-fields td:first-child { width: 34%; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.parse-fields td.prewrap { white-space: pre-wrap; }

/* The review list. One line per flagged thing, three independent controls. */
#package-review { margin-top: 26px; }
.revsection { font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted); margin: 16px 0 2px; padding-bottom: 4px;
  border-bottom: 1px solid var(--line); }
.revsection:first-child { margin-top: 4px; }
.revline { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0;
  border-bottom: 1px solid var(--line); }
.revline:last-child { border-bottom: 0; }
.revline.cleared { opacity: .72; }
.revstate { flex: none; width: 24px; height: 24px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line); background: #fff; cursor: pointer; font-size: 13px;
  line-height: 1; font-weight: 700; }
.revstate.flag { color: var(--flag); border-color: #f0c8c0; background: #fdf2f0; }
.revstate.ok { color: var(--ok); border-color: #c6e2d1; background: #eef7f1; }
.revbody { flex: 1 1 auto; min-width: 0; }
.revhead { display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: 13px; position: relative; }
.revmeta { font-size: 11px; color: var(--muted); margin-top: 2px; }
.revdetail { font-size: 12px; margin-top: 4px; }
.revdetail.warnish { color: #7a5a10; }

/* The people a grouped line stands for: one per line, under the citation.
   They were a comma run inside the citation line, which reads as a clause
   rather than as a list an eye can go down. */
/* What the operator can do about it. Quieter than the finding, because it is
   the answer rather than the problem. */
.revresolve { font-size: 12px; color: var(--muted); margin-top: 4px; }
.revpeople-list .revresolve { margin: 2px 0 6px; }

/* The email draft: read-only, and it looks it. */
.emailpreview {
  white-space: pre-wrap;
  font: 12px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--paper, #fafafa);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 10px 12px;
  margin: 6px 0 8px;
  max-height: 40vh;
  overflow: auto;
}

/* A judgement item is a checkbox, not a flag: nothing here is outstanding and
   red would say it was. */
.revstate.plain { color: var(--muted); border-color: var(--line); background: transparent; }

.revpeople { margin-top: 4px; }
.revpeople-count { font-size: 11px; color: var(--muted); }
.revpeople-list { margin: 2px 0 0; padding-left: 18px; font-size: 12px; }
.revpeople-list li { margin: 0; }
.revcontrols { display: flex; align-items: center; gap: 12px; margin-top: 6px; flex-wrap: wrap; }
.revemail { font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 5px; }
.revcomment { font-size: 12px; padding: 4px 7px; border: 1px solid var(--line);
  border-radius: 6px; min-width: 240px; flex: 1 1 240px; }
.revcomplete { margin-top: 6px; }

/* The investigation stub's three reasons an item is on that list. */
.reasons { margin: 10px 0 0; }
.reasons dt { font-size: 12px; font-weight: 600; margin-top: 8px; }
.reasons dd { margin: 2px 0 0; font-size: 12px; color: var(--muted); }

/* What the platform did on its own: a plain list of steps under each run.
   No bullet glyph -- each line is already a sentence, and a bullet beside a
   sentence that starts with a verb reads as a checklist item somebody has to
   act on. These are a record of what happened. */
#automatic-runs ul.plain { list-style: none; margin: 0.4rem 0 0; padding-left: 0; }
#automatic-runs ul.plain li { padding: 0.1rem 0; }

/* TIGHTER REVIEW ROWS, 2026-09-28. An operator scrolling nine problems and a
   judgement list was scrolling mostly whitespace: every row carried 20px of
   padding, a label on its own line and a comment box below that.

   Nothing is smaller, only closer. The type sizes are unchanged -- a review
   where the text shrank would be a review nobody reads carefully. */
.revline { padding: 6px 0; }
.revdetail { margin-top: 2px; }
.revresolve { margin-top: 2px; }
.revpeople-list .revresolve { margin: 1px 0 3px; }
.revcontrols { gap: 10px; margin-top: 3px; }
.revpeople { margin-top: 2px; }
.revpeople-list { margin: 1px 0 0; }

/* The two ticks, inline and compact: "email" and "FAA list". They were one
   label reading "include in the email", which took a row of its own. */
.revtick { font-size: 11px; color: var(--muted); display: inline-flex;
           align-items: center; gap: 4px; white-space: nowrap; }
.revtick input { margin: 0; }
/* On a bullet the ticks sit after the text, not under it. */
.revpeople-list li > .revtick { margin-left: 8px; }

/* The FAA list: what the FAA approved without. One block per ticked line, the
   operator's own comment last, because that is the reason the line is here. */
.faalist { margin-top: 10px; }
.faarow { padding: 8px 0; border-bottom: 1px solid var(--line); }
.faarow:last-child { border-bottom: 0; }
.faatext { font-size: 14px; }
.faameta { font-size: 11px; color: var(--muted); margin-top: 2px; }
.faameta.warnish { color: #7a5a10; }
.faacomment { font-size: 12px; margin-top: 4px; }
