/*
 * The one stylesheet. v0.4.0 shipped two - styles.css (the original design
 * system) and mebbian.css (the screen layer) - both declaring :root and three
 * colliding selectors, with load order deciding which rule applied. Changing a
 * font size in one file did nothing, twice, for two different reviewers. They
 * are merged in their original load order (design system first, screen layer
 * second), so every collision resolves exactly as it did across two files -
 * and there is now one place a size lives.
 *
 * Root is 18px, down from the 20px the system was first sized against - the
 * review asked for a tad smaller - with every size still computing to 16px or
 * more, which the legibility tests enforce.
 */

/* The design system, from the demo Karim showed CHC and Apogee.
 *
 * Adopted: the palette, the shell, the rail, the spacing rhythm, the button and status
 * vocabulary, the eyebrow-and-serif heading hierarchy, the drawer. Those are what made the
 * reference read as a product, and they are proven in their conference room.
 *
 * NOT adopted: its type scale. The reference bottoms out at 10-13px, which was authored for
 * a laptop. This runs on a conference-room television and MASTER-PLAN section 6 is explicit -
 * base type about 10% larger than feels right, nothing under 16px. So the structure comes
 * across at its own size and the type is scaled UP to our 20px root, rather than our app
 * being scaled down to the reference. tests/surface/test_legibility.py is the check on that
 * and it is unchanged.
 *
 * The rule of thumb in here: structural lengths stay in px because they are the same size on
 * any screen - a 1px rule, an 8px radius, a 220px rail. Type is in rem so it scales with the
 * root, and every value lands at or above 16px.
 *
 * The reference's ".interaction-*" block - the "Ask or act" box - is deliberately absent.
 * The assistant behind it discarded its answer twice out of two on real findings. The
 * validator was right to; it is not something to put in front of a customer.
 */

:root {
  /* Warm paper, deep green, one radius. No pure white and no pure black anywhere. */
  --paper: #fbf8f1;
  --surface: #fffdf8;
  --wash: #f2ede3;
  --ink: #1d1b17;
  --muted: #70695e;
  --line: #ded6c7;
  --green: #104b3a;
  --green-active: #237157;
  --amber: #9b5a16;
  --red: #9f3f35;
  --blue: #355d83;

  --drawer-width: 460px;
  --radius: 8px;
  --rail-width: 220px;
  --topbar-height: 64px;

  /* Kept from the original system: the root that makes 16px the floor rather than the
     ceiling. Every type size below is a fraction of this and none resolves under 16px. */
  font-size: 18px;

  color: var(--ink);
  background: var(--paper);
  font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-synthesis: none;
}

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

html,
body {
  min-width: 0;
  min-height: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  font-size: 1rem;
  line-height: 1.55;
}

button,
a,
input,
textarea,
select {
  font: inherit;
}

button {
  color: inherit;
}

button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid rgba(35, 113, 87, 0.34);
  outline-offset: 3px;
}

body.drawer-open {
  overflow: hidden;
}

/* ---------------------------------------------------------------- topbar */

.topbar {
  min-height: var(--topbar-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 0 26px;
  border-bottom: 1px solid var(--line);
  background: rgba(251, 248, 241, 0.96);
}

/* The brand is the company wordmark. Height is fixed and width follows the lockup's own
   ratio, so a re-exported asset of a different width still sits correctly in the bar. */
.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.brand img {
  height: 28px;
  width: auto;
  display: block;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* Firm rules is reachable and is not a numbered stage. The re-run is not something this
   product demonstrates, so its screen does not sit in the workflow. */
.topbar-link {
  color: var(--green);
  font-size: 0.89rem;
  font-weight: 720;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.topbar-link:hover {
  border-bottom-color: currentColor;
}

.disclosure-chip {
  padding: 7px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--wash);
  color: var(--muted);
  font-size: 0.89rem;
  white-space: nowrap;
}

/* ---------------------------------------------------------------- frame and rail */

.app-frame {
  display: grid;
  grid-template-columns: var(--rail-width) minmax(0, 1fr);
  min-height: calc(100vh - var(--topbar-height));
}

.workflow-rail {
  border-right: 1px solid var(--line);
  background: #f7f2e9;
  padding: 26px 14px;
}

.stage-list {
  display: grid;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.stage-item {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 9px;
  align-items: start;
  width: 100%;
  min-height: 48px;
  padding: 11px 10px;
  border: 0;
  border-left: 2px solid transparent;
  border-radius: 0 7px 7px 0;
  background: transparent;
  cursor: pointer;
  text-align: left;
  text-decoration: none;
}

.stage-item:hover {
  background: rgba(255, 253, 248, 0.74);
}

.stage-number {
  color: #9b9386;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 0.89rem;
  line-height: 1.5;
}

.stage-label {
  color: #817a6f;
  font-size: 0.89rem;
  line-height: 1.35;
}

/* "is-current", not "is-active". The subcontractor screen has a guarantee test that the
   word "active" never reaches it: a suspended licence and a current one look identical in
   the published record, so the screen must never appear to call one Active. A nav class
   carrying that substring into every page would have quietly broken it, and "current" is
   the more accurate word for a nav item anyway. */
.stage-item.is-current {
  border-left-color: var(--green);
  background: #e8eee9;
}

.stage-item.is-current .stage-number,
.stage-item.is-current .stage-label {
  color: var(--green);
  font-weight: 700;
}

/* ---------------------------------------------------------------- work area
 *
 * The column stays at 78rem. Measured before changing it: at a 1601px viewport the content
 * already renders 1560px wide, 97% of the window. The reference's 1180px column would have
 * been a 380px reduction, so it is not adopted. Prose is capped separately by --measure,
 * which is what actually keeps a line readable; tables and evidence want the full width.
 */

.work-area {
  min-width: 0;
  padding: 46px clamp(28px, 5vw, 72px) 64px;
}

.screen-view {
  width: min(100%, 78rem);
  margin: 0 auto;
  min-width: 0;
}

.screen-heading {
  max-width: 46rem;
  margin-bottom: 34px;
}

.eyebrow {
  margin: 0 0 7px;
  color: var(--green);
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 0.89rem;
  line-height: 1.4;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.screen-heading h1 {
  margin: 0 0 9px;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 2.4rem;
  line-height: 1.05;
  letter-spacing: -0.04em;
  font-weight: 400;
}

.screen-heading > p:last-child {
  margin: 0;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.55;
  max-width: none;
}

h2,
h3 {
  text-wrap: balance;
}

/* ---------------------------------------------------------------- buttons */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: 10px 16px;
  border: 1px solid var(--line);
  border-radius: 7px;
  cursor: pointer;
  font-size: 0.89rem;
  font-weight: 720;
  text-decoration: none;
  color: var(--ink);
  background: var(--surface);
}

.button--primary {
  border-color: var(--green);
  background: var(--green);
  color: #fff;
}

.button--primary:hover {
  background: var(--green-active);
}

.button--secondary {
  background: var(--surface);
}

.button--secondary:hover,
.button--quiet:hover {
  border-color: #9ab3a8;
}

.button--quiet {
  background: transparent;
  color: var(--green);
}

.button:disabled {
  cursor: default;
  opacity: 0.62;
}

.text-button {
  border: 0;
  border-bottom: 1px solid currentColor;
  background: transparent;
  color: var(--green);
  cursor: pointer;
  padding: 2px 0;
  font-size: 0.89rem;
  font-weight: 720;
}

/* ---------------------------------------------------------------- status pills */

.status {
  display: inline-flex;
  align-items: center;
  width: max-content;
  min-height: 26px;
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--wash);
  color: var(--muted);
  font-size: 0.89rem;
  font-weight: 780;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.status--sourced {
  border-color: #b9cfc4;
  background: #e8f0eb;
  color: var(--green);
}

.status--needs-review {
  border-color: #e0c39f;
  background: #fbf0df;
  color: #805019;
}

.status--missing {
  border-color: #ddb7af;
  background: #f8e8e5;
  color: var(--red);
}

.status-line {
  padding: 10px 12px;
  border-left: 3px solid var(--green);
  background: #eaf1ed;
  color: var(--green);
  font-size: 0.89rem;
  line-height: 1.45;
}

/* ---------------------------------------------------------------- section furniture */

.case-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-bottom: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.case-strip > div {
  min-width: 0;
  padding: 12px 14px;
  border-right: 1px solid var(--line);
}

.case-strip > div:last-child {
  border-right: 0;
}

.case-strip span,
.field span {
  display: block;
  margin-bottom: 4px;
  color: var(--muted);
  font-size: 0.89rem;
  font-weight: 760;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.case-strip strong,
.field strong {
  display: block;
  font-size: 0.9rem;
  line-height: 1.4;
}

.section-label-row {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 13px;
}

.section-label-row h3 {
  margin: 0;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.2rem;
  line-height: 1.2;
  font-weight: 400;
}

.section-label-row p {
  margin: 0;
  color: var(--muted);
  font-size: 0.89rem;
}

/* ---------------------------------------------------------------- the drawer
 *
 * Evidence detail. Click a crop and the full-size rectangle, the sheet it came from, the
 * exact text and the retrieval date arrive here. No ask box.
 */

.drawer-backdrop {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(29, 27, 23, 0.34);
  opacity: 0;
  transition: opacity 0.18s ease;
}

.drawer-backdrop.is-open {
  opacity: 1;
}

.context-drawer {
  position: fixed;
  z-index: 50;
  top: 0;
  right: 0;
  bottom: 0;
  display: flex;
  width: min(var(--drawer-width), 100vw);
  flex-direction: column;
  overflow: hidden;
  border-left: 1px solid var(--line);
  background: var(--paper);
  transform: translateX(100%);
  transition: transform 0.18s ease;
}

.context-drawer.is-open {
  transform: translateX(0);
}

.drawer-header {
  flex: 0 0 auto;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  align-items: flex-start;
  padding: 26px 24px 20px;
  border-bottom: 1px solid var(--line);
}

.drawer-header h2 {
  margin: 0;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.5rem;
  line-height: 1.08;
  letter-spacing: -0.025em;
  font-weight: 400;
}

.drawer-close {
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  padding: 9px 12px;
  cursor: pointer;
  font-size: 0.89rem;
}

.drawer-close:hover {
  border-color: var(--green-active);
}

.drawer-body {
  min-height: 0;
  flex: 1 1 auto;
  padding: 24px;
  overflow-y: auto;
}

.drawer-body img {
  width: 100%;
  display: block;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--surface);
}

.detail-list {
  display: grid;
  gap: 0;
  margin: 20px 0 0;
}

.detail-list > div {
  padding: 17px 0;
  border-bottom: 1px solid var(--line);
}

.detail-list > div:first-child {
  padding-top: 0;
}

.detail-list dt {
  margin-bottom: 5px;
  color: var(--muted);
  font-size: 0.89rem;
  font-weight: 780;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.detail-list dd {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
}

.source-links {
  display: grid;
  gap: 10px;
  margin-top: 20px;
}

.source-link {
  display: block;
  padding: 12px 13px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--surface);
  color: var(--green);
  font-size: 0.89rem;
  font-weight: 720;
  text-decoration: none;
}

.source-link:hover {
  border-color: var(--green-active);
}

.context-list {
  display: grid;
  gap: 9px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.context-list li {
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--surface);
  padding: 13px 14px;
  font-size: 0.95rem;
  line-height: 1.5;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------- responsive
 *
 * The rail collapses at 720px, which is where the reference puts it. Its 900px block only
 * adjusts work-area padding and a case strip; the horizontal scroller is in the 720 block.
 */

@media (max-width: 900px) {
  .work-area {
    padding-right: 28px;
    padding-left: 28px;
  }

  .case-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .case-strip > div {
    border-bottom: 1px solid var(--line);
  }

  .case-strip > div:nth-child(2n) {
    border-right: 0;
  }

  .case-strip > div:last-child {
    border-bottom: 0;
  }
}

@media (max-width: 720px) {
  .topbar {
    min-height: 58px;
    padding: 10px 16px;
  }

  .app-frame {
    display: block;
    min-height: calc(100vh - 58px);
  }

  .workflow-rail {
    overflow-x: auto;
    border-right: 0;
    border-bottom: 1px solid var(--line);
    padding: 9px 12px;
    scrollbar-width: thin;
  }

  .stage-list {
    display: flex;
    width: max-content;
    gap: 4px;
  }

  .stage-item {
    grid-template-columns: auto auto;
    min-height: auto;
    width: 230px;
    padding: 8px 10px;
    border-left: 0;
    border-bottom: 2px solid transparent;
    border-radius: 6px 6px 0 0;
  }

  .stage-item.is-current {
    border-bottom-color: var(--green);
    border-left-color: transparent;
  }

  .work-area {
    padding: 28px 16px 44px;
  }

  .screen-heading {
    margin-bottom: 24px;
  }

  .screen-heading h1 {
    font-size: clamp(1.8rem, 10vw, 2.2rem);
  }

  .case-strip {
    grid-template-columns: 1fr;
  }

  .case-strip > div {
    border-right: 0;
  }

  .section-label-row {
    align-items: flex-start;
    flex-direction: column;
    gap: 4px;
  }

  .context-drawer {
    width: 100vw;
  }

  .drawer-header {
    padding: 22px 18px 18px;
  }

  .drawer-body {
    padding: 20px 18px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
}


/* ============== the screen layer (formerly mebbian.css) ============== */

/* Mebbian - our screen layer, on top of the design system in styles.css.
 *
 * styles.css owns the shell, the palette and the type hierarchy. This file owns what is
 * ours: the three-state legend, the evidence tables, the crops, the processing columns, the
 * register, screen B. It is layered second, so it inherits those tokens rather than
 * competing with them.
 *
 * Two rules still govern it, unchanged.
 *
 * 1. Legibility across a room. The root stays at 20px and NOTHING here computes below
 *    16px. The reference design bottoms out at 10-13px because it was drawn for a laptop;
 *    this runs on a conference-room television and MASTER-PLAN section 6 is explicit.
 *    tests/surface/test_legibility.py enforces it and was not touched to let this pass.
 *
 * 2. No decoration. No gradients, no shadows standing in for depth, no animation that is
 *    not reporting a real state change. Colour carries exactly three meanings - sourced,
 *    assumption, missing - and is never spent on anything else.
 *
 * "Missing" is deliberately neutral, never red. Red would read as a verdict, and this
 * product does not deliver verdicts. Absent evidence is absent, not bad.
 */

/* ---------------------------------------------------------------- 1 - our names for the
 * system's colours
 *
 * The rules below were written against these names and there are several hundred of them.
 * Rather than rewrite every one, the names are kept and pointed at the design system's
 * palette. One place to look, and the warm paper and deep green reach our screens intact.
 */

:root {
  /* The screen layer's own declaration, kept through the merge: this :root
     block later in the file is the one that wins, and the legibility tests
     read it. */
  font-size: 18px;

  --ground: var(--paper);
  --panel: var(--surface);
  --ink-soft: var(--muted);
  --rule: var(--line);
  --rule-strong: #c4bba8;

  /* The only three colours with meaning, now drawn from the system's own palette. */
  --sourced: var(--green);
  --assumption: var(--amber);
  --missing: var(--muted);

  /* Spacing. Generous - this is read from across a room, not scanned at arm's length. */
  --gap: 1.5rem;
  --gap-tight: 0.75rem;
  --pad: 2rem;

  --measure: 34rem; /* comfortable line length for prose at this size */
}

p {
  max-width: var(--measure);
}

a {
  color: var(--green);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

/* Numbers line up in columns - quantities, dates and money get compared, not read. */
.tabular {
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- 2 - the screen header
 *
 * The eyebrow, the serif title and one line of context, from the design system. The heavy
 * rule under the old header is gone: the shell already separates the work area from the
 * topbar, and a second hard line under every title was the app shouting.
 */

.screen-header {
  max-width: 46rem;
  margin-bottom: 34px;
}

.screen-header h1 {
  margin: 0 0 9px;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 2.4rem;
  line-height: 1.05;
  letter-spacing: -0.04em;
  font-weight: 400;
}

.screen-header .run-context {
  margin: 0;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1.55;
  max-width: none;
}

.screen-header .eyebrow:empty {
  display: none;
}

/* ---------------------------------------------------------------- 4 - standing line */

.standing-line {
  margin-top: var(--pad);
  padding-top: var(--gap-tight);
  border-top: 1px solid var(--rule);
  font-size: 1.05rem;
  color: var(--ink);
  max-width: none;
}

.disclosure {
  font-size: 0.95rem;
  color: var(--ink-soft);
  margin: var(--gap) 0 0;
}

/* ---------------------------------------------------------------- 5 - legend
 *
 * Three single words. Each is distinguished by shape as well as colour, so a projector
 * with poor colour reproduction still separates them.
 */

.legend {
  display: flex;
  gap: var(--gap);
  align-items: center;
  margin: 0 0 var(--gap);
  padding: 0;
  list-style: none;
  font-size: 0.95rem;
}

.legend li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.state-mark {
  width: 0.9rem;
  height: 0.9rem;
  flex: 0 0 auto;
  display: inline-block;
}

/* filled square */
.state-mark--sourced {
  background: var(--sourced);
  border: 2px solid var(--sourced);
}

/* hollow ring */
.state-mark--assumption {
  background: transparent;
  border: 4px solid var(--assumption);
}

/* dashed outline */
.state-mark--missing {
  background: transparent;
  border: 2px dashed var(--missing);
}

.state-word {
  font-weight: 600;
}

.state-word--sourced {
  color: var(--sourced);
}

.state-word--assumption {
  color: var(--assumption);
}

.state-word--missing {
  color: var(--missing);
}

/* ---------------------------------------------------------------- 6 - evidence table
 *
 * Screen B. One row per signal: label, state, value, and the source link with the date it
 * was retrieved. The date is not ornament - evidence with no retrieval time is not
 * evidence.
 */

.evidence {
  width: 100%;
  border-collapse: collapse;
  margin: var(--gap) 0 0;
}

.evidence th {
  text-align: left;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink-soft);
  padding: 0 var(--gap) var(--gap-tight) 0;
  border-bottom: 1px solid var(--rule);
}

.evidence td {
  padding: var(--gap-tight) var(--gap) var(--gap-tight) 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: baseline;
}

.evidence .col-label {
  font-weight: 600;
  white-space: nowrap;
}

.evidence .col-state {
  white-space: nowrap;
}

.evidence .col-source {
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.evidence tr[data-state="missing"] .col-value {
  color: var(--missing);
}

.category-heading {
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-top: var(--gap);
}

.quote-line {
  font-size: 1.1rem;
  color: var(--ink-soft);
  margin: 0.25rem 0 0;
}

.example-tag {
  font-size: 0.95rem;
  color: var(--ink-soft);
  font-weight: 400;
}

/* ---------------------------------------------------------------- 7 - decisions
 *
 * Proceed / Clarify / Hold. Real radio inputs - the estimator's call is recorded state,
 * not a visual flourish.
 */

.decision-set {
  display: flex;
  gap: var(--gap);
  align-items: center;
  margin: var(--gap) 0 0;
  border: 0;
  padding: 0;
}

.decision-set legend {
  font-size: 0.95rem;
  color: var(--ink-soft);
  padding: 0 0 var(--gap-tight);
}

.decision {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1.05rem;
  padding: 0.6rem 1.1rem;
  border: 2px solid var(--rule-strong);
  background: var(--panel);
  cursor: pointer;
}

.decision input {
  width: 1.1rem;
  height: 1.1rem;
  margin: 0;
}

.decision:has(input:checked) {
  border-color: var(--ink);
  font-weight: 600;
}

.button {
  font: inherit;
  font-size: 1.05rem;
  padding: 0.6rem 1.4rem;
  border: 2px solid var(--ink);
  background: var(--ink);
  color: var(--panel);
  cursor: pointer;
}

.button[disabled] {
  background: var(--panel);
  color: var(--missing);
  border-color: var(--rule-strong);
  cursor: not-allowed;
}

.button--quiet {
  background: var(--panel);
  color: var(--ink);
}

/* ---------------------------------------------------------------- 8 - processing
 *
 * Pages flip on the left, findings stack on the right, checks tick underneath. Every
 * number on this screen is counted from the event stream. There is no percentage anywhere,
 * because nothing here knows a percentage.
 */

.processing {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--pad);
  align-items: start;
}

.narration {
  font-size: 1.15rem;
  min-height: 3.2rem;
  padding: var(--gap-tight) 0;
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--gap);
  max-width: none;
}

.run-counters {
  display: flex;
  gap: var(--gap);
  font-size: 0.95rem;
  color: var(--ink-soft);
  margin-bottom: var(--gap);
}

.sheet-stage {
  background: var(--panel);
  border: 1px solid var(--rule);
  padding: var(--gap-tight);
  margin: 0;
}

/* The page render is capped so that the checklist below it stays on screen. A drawing
   sheet is a wide, tall thing and at full column width it pushed the ticking checks off
   the bottom of a 1080p television — which defeats the point of showing them at all.
   object-fit keeps the whole sheet visible inside the cap rather than cropping it. */
.sheet-stage img {
  width: 100%;
  max-height: 40vh;
  object-fit: contain;
  object-position: center;
  display: block;
}

.sheet-stage figcaption {
  font-size: 0.95rem;
  color: var(--ink-soft);
  padding-top: var(--gap-tight);
}

.finding-stack {
  display: flex;
  flex-direction: column;
  gap: var(--gap-tight);
}

.finding-card {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-left: 6px solid var(--ink);
  padding: var(--gap-tight) var(--gap);
}

.finding-card h2 {
  font-size: 1.1rem;
  margin: 0 0 0.25rem;
}

.finding-card p {
  margin: 0;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

/* The checklist. A check that found nothing still ticks, and says so. That is the whole
   point of showing it - it is how the room learns the absence was looked for. */

.checklist {
  list-style: none;
  margin: var(--gap) 0 0;
  padding: 0;
}

/* On a wide screen the checks run in two columns so a full set of them fits above the
   fold. A check nobody can see has not been demonstrated. */
@media (min-width: 1400px) {
  .checklist {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--gap);
  }
}

.check {
  display: grid;
  grid-template-columns: 1.6rem 1fr auto;
  gap: var(--gap-tight);
  align-items: baseline;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.95rem;
}

.check-mark {
  font-weight: 700;
}

.check[data-state="running"] .check-mark {
  color: var(--ink-soft);
}

.check[data-state="clear"] .check-mark {
  color: var(--sourced);
}

.check[data-state="findings"] .check-mark {
  color: var(--assumption);
}

.check[data-state="failed"] .check-mark {
  color: var(--ink);
}

.check-count {
  font-size: 0.95rem;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------- 9 - crops
 *
 * A crop is a real render of their page at real coordinates. The caption states page,
 * sheet, the exact rectangle and the exact text - that caption IS the verification claim,
 * so it is not decoration and it does not get trimmed for tidiness.
 */

.crops {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap);
  margin: var(--gap) 0;
}

.crop {
  margin: 0;
  background: var(--panel);
  border: 1px solid var(--rule);
  padding: var(--gap-tight);
}

.crop img {
  width: 100%;
  display: block;
}

.crop figcaption {
  font-size: 0.95rem;
  color: var(--ink-soft);
  padding-top: var(--gap-tight);
  line-height: 1.45;
}

.crop figcaption .cited-text {
  color: var(--ink);
  font-weight: 600;
}

/* When a crop cannot be rendered we say so, in words, in its place. We never substitute a
   plausible-looking image. */
.unavailable {
  background: var(--panel);
  border: 2px dashed var(--rule-strong);
  padding: var(--gap);
  color: var(--ink-soft);
  font-size: 1rem;
}

.unavailable strong {
  color: var(--ink);
  display: block;
  margin-bottom: 0.35rem;
}

/* ---------------------------------------------------------------- 10 - finding detail */

.finding-grid {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: var(--pad);
  align-items: start;
}

.subhead {
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: var(--gap) 0 var(--gap-tight);
}

.disagreement {
  list-style: none;
  margin: 0;
  padding: 0;
}

.disagreement li {
  padding: var(--gap-tight) 0;
  border-bottom: 1px solid var(--rule);
  font-size: 1.05rem;
}

.disagreement .value {
  font-weight: 700;
}

/* The governing value. Always blank. No value attribute, no placeholder, no suggestion -
   the system does not propose an answer and the markup must not either. */
.governing {
  background: var(--panel);
  border: 2px solid var(--ink);
  padding: var(--gap);
}

.governing label {
  display: block;
  font-weight: 700;
  margin-bottom: var(--gap-tight);
}

.governing input[type="text"],
.governing textarea {
  font: inherit;
  font-size: 1.05rem;
  width: 100%;
  padding: 0.6rem;
  border: 1px solid var(--rule-strong);
  background: var(--panel);
  color: var(--ink);
}

.governing .note {
  font-size: 0.95rem;
  color: var(--ink-soft);
  margin: var(--gap-tight) 0 0;
}

.owner {
  font-size: 1.05rem;
}

.owner .name {
  font-weight: 700;
}

/* Occurrences. Promotion is blocked until every one is confirmed; the button below is
   disabled here and refused on the server. */
.occurrences {
  list-style: none;
  margin: 0;
  padding: 0;
}

.occurrence {
  display: flex;
  align-items: baseline;
  gap: var(--gap-tight);
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 1rem;
}

.occurrence input {
  width: 1.1rem;
  height: 1.1rem;
}

.occurrence[data-confirmed="true"] {
  color: var(--ink-soft);
}

.promotion-gate {
  margin-top: var(--gap);
  font-size: 0.95rem;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------- 11 - rules */

.rule-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rule {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--gap);
  align-items: baseline;
  padding: var(--gap-tight) 0;
  border-bottom: 1px solid var(--rule);
  font-size: 1.05rem;
}

/* Their rule sits beside ours and is marked as theirs. */
.rule-origin {
  font-size: 0.95rem;
  color: var(--ink-soft);
  white-space: nowrap;
}

.rule[data-source="firm"] {
  border-left: 6px solid var(--ink);
  padding-left: var(--gap-tight);
}

.rule[data-source="firm"] .rule-origin {
  color: var(--ink);
  font-weight: 600;
}

.rule-form {
  display: flex;
  gap: var(--gap-tight);
  margin: var(--gap) 0;
}

.rule-form input[type="text"] {
  font: inherit;
  font-size: 1.05rem;
  flex: 1;
  padding: 0.6rem;
  border: 2px solid var(--ink);
  background: var(--panel);
  color: var(--ink);
}

/* The live moment must never show a stack trace. Failures render here, in words. */
.error-panel {
  border: 2px solid var(--assumption);
  background: var(--panel);
  padding: var(--gap);
  margin: var(--gap) 0;
  font-size: 1rem;
}

.error-panel strong {
  display: block;
  color: var(--assumption);
  margin-bottom: 0.35rem;
}

/* ---------------------------------------------------------------- 12 - register */

.register {
  width: 100%;
  border-collapse: collapse;
  margin-top: var(--gap);
}

.register th {
  text-align: left;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink-soft);
  padding: 0 var(--gap) var(--gap-tight) 0;
  border-bottom: 2px solid var(--ink);
}

.register td {
  padding: var(--gap-tight) var(--gap) var(--gap-tight) 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
  font-size: 1rem;
}

.register .blocked {
  color: var(--ink-soft);
}

.draft {
  background: var(--panel);
  border: 1px solid var(--rule);
  padding: var(--gap-tight);
  font-size: 0.95rem;
  white-space: pre-wrap;
  margin: 0;
  font-family: inherit;
}

/* A cross-reference we could not resolve. Named, not hidden. */
.dangling {
  border-left: 6px solid var(--missing);
  padding-left: var(--gap-tight);
}

/* ---------------------------------------------------------------- 13 - stage index */

.stage-list {
  list-style: none;
  margin: var(--gap) 0 0;
  padding: 0;
}

.stage-list li {
  padding: var(--gap-tight) 0;
  border-bottom: 1px solid var(--rule);
  font-size: 1.15rem;
}

.stage-list .order {
  color: var(--ink-soft);
  margin-right: var(--gap-tight);
}

/* ---------------------------------------------------------------- 14 - fixture banner
 *
 * Development only. If fixture-authored material is ever on screen it is stated loudly.
 * Demo mode refuses to render it at all - this banner is the belt to that braces.
 */

.fixture-banner {
  background: var(--ink);
  color: var(--panel);
  padding: var(--gap-tight) var(--pad);
  font-size: 1rem;
  font-weight: 600;
}

/* A panel that is reporting a resting state, not a failure. The words differ, so the
   colour should too: an amber rule beside "no run in progress" reads as an alarm. */
.error-panel.at-rest {
  border-left-color: #8a8a82;
  color: #3a3a36;
}

/* ---------------------------------------------------------------------------
   PRINT

   Architects live on paper and PDF. A register nobody can hand to somebody is a
   screen, not a register.

   What survives printing is the record: the headings, the evidence crops, the
   citations, the owners, the drafts and the decision ledger. What does not is
   everything that only works with a cursor - navigation, buttons, forms, the
   live processing screen - because a printed page cannot be clicked and a
   control that cannot be operated is ink pretending to be a feature.
   --------------------------------------------------------------------------- */
@media print {
  @page {
    margin: 14mm;
  }

  html,
  body {
    background: #fff;
    color: #000;
    font-size: 10.5pt;
  }

  .app-frame {
    display: block;
  }

  .work-area {
    padding: 0;
  }

  .screen-view {
    width: 100%;
    max-width: none;
  }

  /* The shell. A rail and a topbar are for a cursor and a screen; on paper they are ink
     spent on navigation nobody can use. The drawer likewise - whatever it was showing is
     already on the page it came from. */
  .topbar,
  .workflow-rail,
  .context-drawer,
  .drawer-backdrop,
  .screen-nav,
  .button,
  button,
  form,
  .rule-form,
  .promotion,
  .decision,
  .print-action,
  .fixture-banner,
  #stream-error,
  .finding-stack a .detail {
    display: none !important;
  }

  /* Links print as text; a blue underline on paper is noise. */
  a {
    color: inherit;
    text-decoration: none;
  }

  /* The header carries the project identity, which is what makes a printout
     identifiable once it has left the screen. */
  .screen-header {
    border-bottom: 1pt solid #000;
    padding-bottom: 4mm;
    margin-bottom: 6mm;
  }

  .run-context {
    font-size: 10pt;
    color: #000;
  }

  /* Evidence is the point of the document. Never split a crop across a page. */
  figure,
  .crop,
  .crop-figure,
  .register tr,
  .finding-card {
    break-inside: avoid;
    page-break-inside: avoid;
  }

  img {
    max-width: 100%;
  }

  .draft,
  pre {
    white-space: pre-wrap;
    border: 0.5pt solid #999;
    font-size: 9pt;
  }

  /* A disclosure is closed on screen for framing reasons; on paper the record
     should be complete. */
  details {
    display: block;
  }

  details > summary {
    font-weight: 600;
    list-style: none;
  }

  details > *:not(summary) {
    display: block !important;
  }

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

  th,
  td {
    border-bottom: 0.5pt solid #bbb;
    padding: 2mm 3mm;
    vertical-align: top;
  }

  thead {
    display: table-header-group;
  }
}

/* The control that starts a print. Hidden from the printout itself. */
.print-action {
  margin: 0 0 1.2rem 0;
}

/* The upload control. A file input and a button on one line, like the rule box. */
.upload-form {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  margin: 0.5rem 0 0.75rem 0;
}

.upload-form input[type="file"] {
  flex: 1 1 auto;
  padding: 0.5rem;
  border: 1px solid #b9b7ad;
  background: #fff;
}

/* ---------------------------------------------------------------- 15 · screen B
 *
 * Four things the five-row table could not say, and one rule about all of them.
 *
 * The legend is still three words. Sourced / Assumption / Missing is how well a fact is
 * supported. Who is speaking - a public registry, or the firm describing itself - is a
 * different question, and it gets its own treatment rather than a fourth colour. Spending
 * the legend on it would cost the legend its meaning.
 */

/* The source in English. Set to be read, not as fine print: this is the line that tells
   somebody a certificate came from the party being checked. */
.source-line {
  display: block;
  font-size: 0.95rem;
  color: var(--ink-soft);
  line-height: 1.4;
}

/* Self-reported evidence carries a visible mark. Not an alarm - a certificate of insurance
   from the firm is ordinary and legitimate - but never silently equal to a registry. */
.source-line--self {
  color: var(--ink);
  border-left: 3px solid var(--assumption);
  padding-left: 0.5rem;
}

.self-reported {
  display: block;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--assumption);
  letter-spacing: 0.02em;
}

/* Where the search looked, on a row that found nothing. The difference between "we do not
   know" and "nobody checked". */
.searched {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.95rem;
  color: var(--ink-soft);
}

/* Why an assumption was drawn. */
.basis {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.95rem;
  color: var(--assumption);
}

/* Also found. Always on screen, so two firms stay comparable side by side. */
.also-found {
  background: var(--panel);
  border: 1px solid var(--rule);
  padding: var(--gap);
}

.also-found-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.also-found-list li {
  padding: var(--gap-tight) 0;
  border-bottom: 1px solid var(--rule);
}

.also-found-list li:last-child {
  border-bottom: 0;
}

.also-headline {
  display: block;
  font-size: 1.05rem;
  font-weight: 700;
}

.also-detail {
  display: block;
  font-size: 1rem;
  color: var(--ink-soft);
  margin-top: 0.2rem;
}

/* An empty section is a statement, so it reads as one rather than as a gap. */
.also-empty {
  margin: 0;
  color: var(--ink-soft);
  font-size: 1rem;
}

/* Identity candidates. The ambiguity is the output; this is deliberately a plain list with
   no ordering cue, because a first row reads as a recommendation. */
.candidates td {
  vertical-align: top;
}

/* A disposition's evidence snapshot: what was on screen when somebody made the call. */
.snapshot {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.95rem;
}

.snapshot li {
  padding: 0.2rem 0;
}

.snapshot-label {
  font-weight: 600;
  margin-right: 0.4rem;
}

.snapshot-text {
  color: var(--ink-soft);
  margin-left: 0.4rem;
}

/* ---------------------------------------------------------------- 16 · the lookup form
 *
 * Screen B's way in. A firm name leads because that is what somebody has first; the
 * document is the alternative, not the price of entry.
 */

.lookup-form {
  display: grid;
  gap: var(--gap-tight);
  max-width: 46rem;
  margin: 0 0 var(--gap);
  padding: var(--gap);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.lookup-row {
  display: grid;
  gap: 0.3rem;
}

.field-label {
  font-size: 0.89rem;
  font-weight: 700;
  color: var(--ink);
}

.field-optional {
  margin-left: 0.4rem;
  color: var(--muted);
  font-size: 0.89rem;
  font-weight: 400;
}

.lookup-form input[type="text"] {
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--paper);
  color: var(--ink);
  font-size: 1rem;
}

.lookup-form input[type="file"] {
  font-size: 0.9rem;
}

.lookup-form .button {
  justify-self: start;
  margin-top: 0.3rem;
}

/* ------------------------------------------------- v0.3: the empty start, staged card */
.dropzone {
  margin: 3rem auto 0;
  max-width: 34rem;
  border: 2px dashed var(--rule-strong, #b3ad9f);
  border-radius: 8px;
  padding: 3rem 2rem;
  text-align: center;
  background: var(--panel, #fffdf8);
}
.dropzone-title { font-size: 1.3rem; font-weight: 700; margin: 0 0 1rem; }
.dropzone-hint { color: var(--ink-soft, #70695e); font-size: 0.89rem; margin-top: 1rem; }
.dropzone-form input[type="file"] { margin: 0 auto 1rem; display: block; }

.staged-card {
  margin: 2rem 0;
  border: 1px solid var(--rule, #ded6c7);
  border-radius: 8px;
  padding: 1.5rem 1.75rem;
  background: var(--panel, #fffdf8);
  max-width: 34rem;
}
.staged-name { font-weight: 750; font-size: 1.1rem; margin: 0 0 1rem; overflow-wrap: anywhere; }
.staged-hint { color: var(--ink-soft, #70695e); margin: 0 0 0.75rem; }
.staged-actions { display: inline-flex; align-items: center; gap: 1rem; margin: 0 1rem 0 0; }
.staged-fresh { font-size: 0.89rem; color: var(--ink-soft, #70695e); }

/* ------------------------------------------------- badges: sample, draft */
.badge {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: 0.89rem;
  font-weight: 750;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  vertical-align: middle;
}
.badge--sample { background: #e8eee9; color: #104b3a; border: 1px solid #9ab3a8; }
.badge--draft { background: var(--wash, #f2ede3); color: var(--ink-soft, #70695e); border: 1px solid var(--rule, #ded6c7); }
.label-optional { color: var(--ink-soft, #70695e); font-weight: 400; font-size: 0.89rem; margin-left: 0.4rem; }
.draft-cell .copy-draft { margin-left: 0.6rem; }

/* ------------------------------------------------- prev/next, topbar reset */
.stage-steps {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 3rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule, #ded6c7);
}
.stage-step { font-weight: 720; text-decoration: none; }
.stage-step--next { margin-left: auto; }
.topbar-reset { display: inline; margin: 0; }
.topbar-link--button { border: 0; background: transparent; cursor: pointer; padding: 0; font: inherit; }

/* ------------------------------------------------- the condensed run view */
.event-log { margin-top: 2.5rem; }
.event-log summary { cursor: pointer; color: var(--ink-soft, #70695e); font-size: 0.89rem; }
.event-log-lines {
  margin: 0.75rem 0 0;
  padding-left: 1.5rem;
  font-size: 0.89rem;
  color: var(--ink-soft, #70695e);
  max-height: 24rem;
  overflow-y: auto;
}
.set-aside-list { font-size: 0.89rem; color: var(--ink-soft, #70695e); padding-left: 1.1rem; }
.set-aside-list li { margin-bottom: 0.5rem; }

@media print {
  .stage-steps, .staged-actions, .event-log, .topbar-reset, .copy-draft { display: none !important; }
}

/* ------------------------------------------------------- rules: remove control */

/* A rule's row: text, origin, and - firm rules only - Edit and Remove. */
.rule { grid-template-columns: 1fr auto auto auto; position: relative; }
.rule-remove { margin: 0; }
.rule-remove .button { padding: 0.15rem 0.7rem; font-size: 0.89rem; }

/* ------------------------------------------------------- drag and drop states */

/* A file dragged over a real drop target says so; everywhere else a drop is
   swallowed by dropzone.js rather than navigating the browser into the PDF. */
.dropzone--over {
  outline: 3px dashed var(--ink);
  outline-offset: 4px;
}
.drop-message {
  color: var(--ink-soft, #70695e);
  font-size: 0.9rem;
  margin: 0.5rem 0 0;
}

/* --------------------------------------------- subcontractor qualification */

/* One box leads. The ask and the run button on one line; the file drop under it. */
.ask-form { margin: 0 0 var(--gap); }
.ask-row { display: flex; gap: var(--gap-tight); }
.ask-row input[type="text"] {
  font: inherit;
  font-size: 1.05rem;
  flex: 1;
  padding: 0.7rem;
  border: 2px solid var(--ink);
  background: var(--panel);
  color: var(--ink);
}
.ask-attach {
  display: flex;
  align-items: baseline;
  gap: var(--gap-tight);
  margin-top: 0.6rem;
  flex-wrap: wrap;
}
.ask-attach-label { color: var(--ink-soft); font-size: 0.9rem; }

/* The research log: live on the progress page, collapsed to its counts after. */
.activity { margin: var(--gap) 0; }
.activity summary { cursor: pointer; font-weight: 600; }
.activity-lines { margin: 0.5rem 0 0; padding-left: 1.4rem; }
.activity-lines li {
  margin-bottom: 0.35rem;
  color: var(--ink-soft);
  font-size: 0.95rem;
}

/* Evidence left, the firm and its quote in a panel right - the reviewer's layout. */
.qual-results {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 16rem;
  gap: var(--gap);
  align-items: start;
}
.qual-evidence { overflow-x: auto; }
.qual-panel { border: 1px solid var(--rule); padding: var(--gap-tight); }
.qual-firm { margin: 0 0 0.5rem; font-size: 1.15rem; }
@media (max-width: 900px) {
  .qual-results { grid-template-columns: 1fr; }
}

/* Start over: the destructive control confirms in its own disclosure, because a
   native confirm dialog would block the whole browser. */
.startover { position: relative; }
.startover > summary { list-style: none; cursor: pointer; }
.startover > summary::-webkit-details-marker { display: none; }
.startover[open] > .startover-confirm {
  position: absolute;
  right: 0;
  top: calc(100% + 0.4rem);
  z-index: 10;
  background: var(--panel);
  border: 2px solid var(--ink);
  padding: var(--gap-tight);
  width: 20rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-size: 0.9rem;
}

/* Inside the qualification panel the legend must never breach the card border -
   the reviewer shot the Missing chip spilling outside it. Wrap, and tighten. */
.qual-panel .legend {
  flex-wrap: wrap;
  gap: var(--gap-tight);
  font-size: 0.89rem;
}

/* Edit opens a floating panel anchored to its row - the same disclosure pattern
   as Start over, so nothing can block the browser. */
.rule-edit { margin: 0; }
.rule-edit > summary { list-style: none; cursor: pointer; }
.rule-edit > summary::-webkit-details-marker { display: none; }
.rule-edit[open] > .rule-edit-form {
  position: absolute;
  right: 0;
  top: calc(100% + 0.3rem);
  z-index: 10;
  background: var(--panel);
  border: 2px solid var(--ink);
  padding: var(--gap-tight);
  width: min(34rem, 90%);
  display: flex;
  gap: var(--gap-tight);
}
.rule-edit-form input[type="text"] {
  font: inherit;
  font-size: 0.95rem;
  flex: 1;
  padding: 0.5rem;
  border: 2px solid var(--ink);
  background: var(--panel);
  color: var(--ink);
}
