/* ─────────────────────────────────────────────────────────────
   Academian Student Access Inventory — shared styles
   Loaded by login.html, index2.html and jobs.html.  The accent is the same
   #0D6EFD the generated workbook uses for its header row, so the tool and its
   output read as one thing.
   ───────────────────────────────────────────────────────────── */

:root {
  /* The tool is light, always — it does not follow the operating system.
     color-scheme pins the parts the browser paints itself: inputs, checkboxes,
     scrollbars and autofill. Without it a machine set to dark draws dark form
     controls inside these light panels, which is where text goes invisible. */
  color-scheme: light;

  --accent:      #0D6EFD;
  --accent-dark: #0B5ED7;
  --accent-soft: #E8F1FF;
  /* Button fill is its own token: a white label on --accent lands on exactly
     4.50:1 with no margin, so the fill is stepped down to keep a margin. */
  --accent-btn:  #0B62E4;

  --ground:  #F5F7FA;
  --surface: #FFFFFF;
  --panel:   #F0F3F7;
  --rule:    #DCE3EC;

  --ink:   #14181F;
  --ink-2: #47535F;
  --ink-3: #636E7A;      /* was #6E7B88 — 4.33:1 on white, under the 4.5 floor */

  /* Two different jobs, so two tokens: --rule draws decorative separators and
     may stay faint; --field draws the boundary of a control, which WCAG 1.4.11
     requires to clear 3:1 or the control is not perceivable. The inputs here
     are barely tinted, so that border is the only thing defining them. */
  --field: #8390A0;

  --pending:    #636E7A;   /* was #6E7B88 — 3.78:1 in its pill */
  --processing: #A05F00;   /* was #B26A00 — 3.86:1 in its pill */
  --completed:  #0E7C4A;
  --failed:     #C0341D;
  --pending-bg:    #EDF0F3;
  --processing-bg: #FFF3DF;
  --completed-bg:  #E2F3EA;
  --failed-bg:     #FCE9E5;

  --shadow: 0 1px 2px rgba(20,24,31,.05), 0 8px 28px rgba(20,24,31,.06);
  --radius: 10px;

  --sans: "Segoe UI", Calibri, system-ui, -apple-system, Roboto, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
}

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

/* The browser hides [hidden] elements with its own `display: none`, and ANY
   author rule that sets display beats it — author styles win over the user
   agent's regardless of specificity. `button, .btn` below sets
   `display: inline-flex`, so every button this page hides in script stayed on
   screen: Generate sat in the New Report footer from the moment the dialog
   opened, beside Queue Report, and clicking it did nothing because there was
   no approved list behind it yet. Same for Check Sheet after a preview, Retry
   all, and the Download link on an unfinished report. One rule fixes the whole
   class of them, and !important is what it takes to outrank the display
   declarations further down. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* ── top bar ─────────────────────────────────────────────── */
/* There is only one page — 'New report' is a dialog over it — so the bar
   carries identity and the session, and no navigation. */
.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
  position: sticky; top: 0; z-index: 20;
}
.topbar-in {
  max-width: 1180px; margin: 0 auto;
  padding: 0 28px; min-height: 60px;
  display: flex; align-items: center; gap: 18px;
}
.brand {
  display: flex; align-items: center; gap: 11px;
  font-weight: 700; font-size: 15px; letter-spacing: -.01em;
  text-decoration: none; color: var(--ink); line-height: 1.2;
}
.brand .logo { width: 28px; height: 28px; flex: none; display: block; }
.brand small {
  display: block; font-weight: 500; color: var(--ink-3);
  font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  margin-top: 2px;
}
.spacer { flex: 1; }
.who { font-size: 13px; color: var(--ink-3); white-space: nowrap; }

/* Actions live in the bar, so they stay put as the list scrolls. */
.topbar button { padding: 8px 15px; font-size: 13.5px; }
.topbar .link { padding: 4px 6px; }
.bar-sep {
  width: 1px; height: 24px; background: var(--rule); flex: none; margin: 0 4px;
}

/* ── layout ──────────────────────────────────────────────── */
.page {
  max-width: 1180px; margin: 0 auto;
  padding: 32px 28px 80px;
  display: flex; flex-direction: column; gap: 24px;
}

@media (max-width: 700px) {
  .topbar-in { padding: 10px 16px; flex-wrap: wrap; gap: 12px; }
  .page { padding: 22px 16px 60px; }
}
h1 {
  margin: 0; font-size: 24px; font-weight: 700; letter-spacing: -.015em;
  text-wrap: balance;
}
.sub { margin: 6px 0 0; color: var(--ink-2); font-size: 14.5px; max-width: 70ch; }

.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 24px 26px;
}

/* ── forms ───────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 18px; }
label { font-size: 13px; font-weight: 650; color: var(--ink); }
.hint { font-size: 12px; color: var(--ink-3); }

input[type=text], input[type=email], input[type=url], input[type=password],
textarea, input[type=file] {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--field);
  border-radius: 8px;
  background: var(--ground);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  outline: none;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
textarea { min-height: 92px; resize: vertical; font-family: var(--mono); font-size: 13px; }
input:focus, textarea:focus {
  border-color: var(--accent);
  background: var(--surface);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
input[type=file] { padding: 8px; background: var(--surface); font-size: 13px; }

.or {
  display: flex; align-items: center; gap: 12px;
  color: var(--ink-3); font-size: 12px; margin: -4px 0 14px;
}
.or::before, .or::after { content: ""; height: 1px; background: var(--rule); flex: 1; }

/* ── submission mode switch ──────────────────────────────── */
.modes { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.mode {
  display: block; text-align: left;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 14px 16px; font-weight: 650; font-size: 14.5px;
  box-shadow: var(--shadow);
}
.mode small {
  display: block; font-weight: 400; font-size: 12.5px;
  color: var(--ink-3); margin-top: 3px;
}
.mode:hover { background: var(--panel); }
.mode[aria-selected="true"] {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px var(--accent) inset, var(--shadow);
}
.mode[aria-selected="true"] small { color: var(--accent-dark); }
@media (max-width: 640px) { .modes { grid-template-columns: 1fr; } }

button, .btn {
  font: inherit; font-size: 14px; font-weight: 650;
  padding: 10px 18px; border-radius: 8px;
  border: 1px solid transparent;
  background: var(--accent-btn); color: #fff;
  cursor: pointer; text-decoration: none;
  display: inline-flex; align-items: center; gap: 8px;
  transition: background .15s, opacity .15s;
}
button:hover:not(:disabled), .btn:hover { background: var(--accent); }
button:disabled { opacity: .55; cursor: not-allowed; }
button.ghost, .btn.ghost {
  background: transparent; color: var(--ink-2); border-color: var(--rule);
}
button.ghost:hover:not(:disabled), .btn.ghost:hover {
  background: var(--panel); color: var(--ink);
}
button.link {
  background: none; border: none; color: var(--ink-3);
  padding: 4px 6px; font-weight: 500; font-size: 13px;
}
button.link:hover { background: none; color: var(--failed); text-decoration: underline; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── messages ────────────────────────────────────────────── */
.msg { padding: 11px 14px; border-radius: 8px; font-size: 13.5px; margin-top: 14px; }
.msg.err  { background: var(--failed-bg);    color: var(--failed);    border-left: 3px solid var(--failed); }
.msg.ok   { background: var(--completed-bg); color: var(--completed); border-left: 3px solid var(--completed); }
.msg.info { background: var(--accent-soft);  color: var(--accent-dark); border-left: 3px solid var(--accent); }
.msg[hidden] { display: none; }

/* ── table ───────────────────────────────────────────────── */
.scroller { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; min-width: 860px; }
th {
  text-align: left; font-size: 11px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3); font-weight: 650;
  padding: 0 12px 9px 0; border-bottom: 1px solid var(--rule); white-space: nowrap;
}
td { padding: 11px 12px 11px 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
tbody tr:hover td { background: var(--panel); }
td.num, th.num { text-align: right; font-family: var(--mono);
                 font-variant-numeric: tabular-nums; font-size: 13px; white-space: nowrap; }

.course { font-weight: 650; font-size: 14px; }
.course small { display: block; font-weight: 400; color: var(--ink-3);
                font-family: var(--mono); font-size: 11.5px; }

.pill {
  display: inline-block; padding: 3px 9px; border-radius: 20px;
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  white-space: nowrap;
}
.pill.PENDING    { background: var(--pending-bg);    color: var(--pending); }
.pill.PROCESSING { background: var(--processing-bg); color: var(--processing); }
.pill.COMPLETED  { background: var(--completed-bg);  color: var(--completed); }
.pill.FAILED     { background: var(--failed-bg);     color: var(--failed); }

.stage {
  font-size: 12.5px; color: var(--ink-2); font-family: var(--mono);
  display: inline-block;          /* ::first-letter needs a block box */
}
/* Stage text comes from log labels, which are lowercase on purpose.
   Capitalise it here so the UI reads properly without renaming them. */
.stage::first-letter { text-transform: uppercase; }
.err-text {
  font-size: 12.5px; color: var(--failed);
  max-width: 42ch; word-break: break-word;
}
.tally { font-family: var(--mono); font-size: 12.5px; white-space: nowrap; }
.tally .c { color: var(--completed); font-weight: 700; }
.tally .n { color: var(--ink-3); }
.tally .e { color: var(--failed); font-weight: 700; }

.empty { padding: 44px 20px; text-align: center; color: var(--ink-3); font-size: 14px; }

/* ── job accordion ───────────────────────────────────────── */
#batches { display: flex; flex-direction: column; gap: 12px; }

.batch {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.batch-head {
  display: flex; align-items: center; gap: 14px;
  padding: 15px 20px; cursor: pointer;
  user-select: none;
}
.batch-head:hover { background: var(--panel); }
.batch.open .batch-head { border-bottom: 1px solid var(--rule); }

.chev {
  width: 0; height: 0; flex: none;
  border-left: 6px solid var(--ink-3);
  border-top: 4.5px solid transparent;
  border-bottom: 4.5px solid transparent;
  transition: transform .15s ease;
}
.batch.open .chev { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .chev { transition: none; } }

.batch-title {
  flex: 1; min-width: 0;
  font-weight: 650; font-size: 14.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.batch-title small {
  display: block; font-weight: 400; color: var(--ink-3);
  font-size: 12px; margin-top: 2px;
}
.batch-count {
  font-family: var(--mono); font-size: 12.5px; color: var(--ink-2);
  white-space: nowrap;
}
.batch-count .e { color: var(--failed); font-weight: 700; }

/* The figure the client quotes: total pages across every counted file. */
.batch-pages {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: 17px; font-weight: 700; color: var(--accent-dark);
  line-height: 1.05; text-align: right; white-space: nowrap; flex: none;
  min-width: 62px;
}
.batch-pages small {
  display: block; font-family: var(--sans); font-size: 10px; font-weight: 500;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
  margin-top: 1px;
}
td.pages { font-weight: 650; color: var(--ink); }
.grand { color: var(--accent-dark); font-variant-numeric: tabular-nums; }
/* The inventory mark beside the page title.
   Both dimensions are fixed and flex:none is set, because this image is 1024px
   square: without a size rule it once filled its whole container at around
   100px. The width/height attributes in the markup repeat the same numbers, so
   it is still the right size for the instant before the stylesheet arrives. */
.page-head { display: flex; align-items: center; gap: 14px; }
.page-mark {
  width: 40px; height: 40px; flex: none;
  border-radius: 9px; object-fit: cover; display: block;
  box-shadow: 0 1px 2px rgba(20, 24, 31, .12);
}
.page-head h1 { margin: 0; }
@media (max-width: 640px) {
  .page-mark { width: 32px; height: 32px; }
}

/* The trash mark, drawn inline in the markup. Stroked rather than filled so it
   stays legible at 14px and takes the colour of the button it sits in. */
.ico {
  width: 14px; height: 14px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.topbar .ico { width: 15px; height: 15px; }

/* Anything that destroys something reads in the failure colour, not the
   ordinary one, so it is never mistaken for a neutral action. */
/* One course and its own report, repeated. Each block is boxed so it reads as
   a unit — three loose fields per course would run together once there are
   two or three of them on screen. */
.pane-hint { margin: 0 0 12px; }
.pair {
  border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 14px 16px 4px; margin-bottom: 12px; background: var(--surface);
}
.pair-head {
  display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
}
.pair-n {
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 650;
}
.pair-n b { color: var(--ink-2); font-weight: 700; }
.pair-head .p-drop { margin-left: auto; }
.pair .or { margin: 10px 0; }
button.add-pair { width: 100%; justify-content: center; }

/* A button that is only an icon still needs to be hittable and still needs a
   name. The name comes from aria-label and title, since there is no text; the
   size is set here because padding sized for a word collapses without one.
   32px square clears the 24px minimum target with room for a fat finger. */
button.icon-only {
  width: 32px; height: 32px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 7px;
}
button.icon-only .ico { width: 16px; height: 16px; }
button.link.icon-only:hover:not(:disabled) {
  background: var(--failed-bg); text-decoration: none;
}

button.danger { color: var(--failed); }
button.ghost.danger { border-color: var(--failed); }
button.link.danger { color: var(--ink-3); }
button.link.danger:hover:not(:disabled) { color: var(--failed); }
button.ghost.danger:hover:not(:disabled) {
  background: var(--failed-bg); color: var(--failed);
}

/* A report row opens its own file list, so it has to look openable. The cursor
   and a hover tint carry that; the controls inside keep their own cursor. */
tr.clickable { cursor: pointer; }
tr.clickable:hover td { background: var(--accent-soft); }
tr.clickable a, tr.clickable button, tr.clickable input { cursor: default; }

/* The file list is wider than the New report form — file names need the room. */
.modal.wide { max-width: 1000px; }
.modal.wide .scroller { max-height: 58vh; overflow: auto; }
.modal.wide table { min-width: 720px; }
.modal.wide td.note {
  color: var(--ink-2); font-size: 12.5px; max-width: 320px;
}
.row-failed td { background: var(--failed-bg); }
.row-failed td .e { font-weight: 650; }
.modal-head .spacer { flex: 1; }

/* Row controls sit in one cell: sized down to the row, and never wrapping so
   Retry and Remove stay on the same line as the status beside them. */
.row-actions { white-space: nowrap; }
.row-actions .btn, .row-actions button.retry {
  padding: 6px 12px; font-size: 13px;
}
/* --accent-dark, not --accent-btn: the latter is a BACKGROUND token meant to
   carry white text. As ink it measures 5.84:1 on the surface and 5.25:1 on the
   row's hover background, both clear of the 4.5 floor. */
button.retry { border-color: var(--accent-dark); color: var(--accent-dark); }
button.retry:hover:not(:disabled) { background: var(--accent-soft); color: var(--accent-dark); }
button.retry:disabled { opacity: .6; }
button.retry-load { color: var(--failed); font-weight: 650; text-decoration: underline; }

/* ── notes on a file row ───────────────────────────────────────
   The Note column answers two different questions. "Download failed" says why
   a row has no count; "2 copies in course" says something extra about a row
   that counted perfectly well. As identical grey text the second one read as a
   complaint, so asides are tagged and failures are left as prose. */
.note-tag {
  display: inline-block; padding: 1px 7px;
  border: 1px solid var(--line); border-radius: 999px;
  font-size: 11px; font-weight: 600; color: var(--ink-3);
  white-space: nowrap; cursor: help;
}
.note-tag.edited {
  margin-left: 6px; text-transform: uppercase; letter-spacing: .03em;
}
/* Both kinds of duplicate share one look, because they are one idea. Not the
   failure colour: nothing is wrong with either row. Whether the pages count is
   said by the Pages cell — struck through means not added — so the tag does not
   have to carry it as well. */
.note-tag.dup { background: var(--accent-soft); border-color: var(--accent-soft); }

/* ── Remediate? ────────────────────────────────────────────────
   The one cell on the file list that is changed rather than read, so it is
   drawn as a control and not as text: a pill that states the current answer
   and flips it when clicked. Fixed width, because Y and N are different widths
   and a column that jogs sideways as it is worked down is hard to aim at. */
/* The Remediate? cell's styles lived here. The column was taken off this
   screen — scoping happens in the workbook now — so nothing can carry
   these classes any more. */

/* Sits under the key, and reads as prose because it explains an action rather
   than labelling a value. */
.key-note { margin: 10px 2px 0; max-width: 78ch; }

.note-missing { color: var(--ink-2); cursor: help; }
.note-error { color: var(--ink-2); }

/* A repeated row carries the same figure as the row that owns it, so the two
   must not read alike. Struck through and muted says "this is how many pages it
   is, and it is not being added again" without needing a word for it. */
.repeat { text-decoration: line-through; opacity: .75; }

/* Key to the Pages column, under the table. Four values, four sentences: the
   screen explains itself rather than needing someone to explain it. */
.key {
  display: flex; flex-wrap: wrap; gap: 6px 22px;
  margin: 14px 2px 2px; padding: 12px 14px 10px;
  border-top: 1px solid var(--line);
  font-size: 12.5px; color: var(--ink-2);
}
.key > div { display: flex; align-items: baseline; gap: 8px; }
.key dt { font-family: var(--mono); font-size: 12px; font-weight: 650; }
.key dd { margin: 0; }
.key .c { color: var(--completed); }
.key .n { color: var(--ink-3); }
.key .e { color: var(--failed); }

.batch-actions { display: flex; gap: 8px; }
.batch-actions .btn { padding: 7px 13px; font-size: 13px; }

.batch-body { padding: 0 0 6px; }
.batch-bar {
  display: flex; align-items: center; gap: 16px;
  padding: 12px 20px; background: var(--panel);
  border-bottom: 1px solid var(--rule);
}
.sel-all {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 500; color: var(--ink-2); cursor: pointer;
}
.batch-bar button { padding: 7px 13px; font-size: 13px; }
.batch-body table { min-width: 780px; }
.batch-body th:first-child, .batch-body td:first-child { padding-left: 20px; }
.batch-body th:last-child,  .batch-body td:last-child  { padding-right: 20px; }
.batch-body th { padding-top: 10px; }
.batch-body tbody tr:last-child td { border-bottom: none; }
input[type=checkbox] { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }
input[type=checkbox]:disabled { cursor: not-allowed; opacity: .4; }

@media (max-width: 700px) {
  .batch-head { flex-wrap: wrap; gap: 8px 12px; }
  .batch-count, .batch-actions { margin-left: 22px; }
}

/* ── modal ───────────────────────────────────────────────── */
body.modal-open { overflow: hidden; }

.modal-back {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(9, 13, 18, .55);
  display: flex; align-items: center; justify-content: center;
  padding: 3vh 20px;
}
.modal-back[hidden] { display: none; }

.modal {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 12px;
  box-shadow: 0 24px 64px rgba(0,0,0,.34);
  width: 100%; max-width: 880px;
  display: flex; flex-direction: column;
  max-height: 94vh;          /* the body scrolls only if it truly cannot fit */
}

/* Header carries the title, the mode switch and the close button on one line —
   the switch used to sit in the body and pushed the form into a scrollbar. */
.modal-head {
  display: flex; align-items: center; gap: 18px;
  padding: 14px 18px; border-bottom: 1px solid var(--rule);
}
.modal-title-wrap { flex: none; min-width: 0; }
.modal-head h2 { margin: 0; font-size: 16px; font-weight: 700; letter-spacing: -.01em; }
.modal-head .hint { margin-top: 1px; font-size: 11.5px; }
.modal-head .modes {
  flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; min-width: 0;
}
.modal-head .mode {
  padding: 8px 11px; font-size: 13px; box-shadow: none; border-radius: 8px;
  overflow: hidden;
}
.modal-head .mode small {
  font-size: 11px; margin-top: 1px; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.modal-body { padding: 16px 18px; overflow-y: auto; }
.modal-body .field { margin-bottom: 12px; }
.modal-body .field:last-child { margin-bottom: 0; }
.modal-body textarea { min-height: 68px; }
.modal-body .or { margin: -2px 0 10px; }
.modal-body .drop { padding: 12px 14px; }
.modal-body .hint { font-size: 11.5px; }

@media (max-width: 760px) {
  .modal-head { flex-wrap: wrap; gap: 12px; }
  .modal-head .modes { order: 3; flex-basis: 100%; }
}
.modal-foot {
  display: flex; justify-content: flex-end; gap: 10px;
  padding: 14px 22px; border-top: 1px solid var(--rule);
  background: var(--panel); border-radius: 0 0 12px 12px;
}

/* ── the confirm dialog ────────────────────────────────────────
   Sized to its sentence, not to the report tables the other modals hold. */
.modal.narrow { max-width: 460px; }
.confirm-body { margin: 0; color: var(--ink-2); font-size: 14px; line-height: 1.55; }

/* A filled destructive button. `button.danger` alone only recolours the TEXT,
   which on the filled default background is red on blue — so the confirm button
   needs the fill itself, not just the ink. White on #C0341D measures 6.1:1. */
button.btn.danger, .btn.danger {
  background: var(--failed); border-color: var(--failed); color: #fff;
}
button.btn.danger:hover:not(:disabled), .btn.danger:hover { background: #9E2B18; }

/* Compact mode cards — they are a two-way switch, not a feature grid. */
.modal-body .mode { padding: 11px 14px; font-size: 13.5px; }
.modal-body .mode small { font-size: 12px; margin-top: 2px; }

/* ── file drop zone ──────────────────────────────────────── */
.drop {
  display: flex; align-items: center; gap: 13px;
  padding: 15px 16px;
  border: 1.5px dashed var(--field); border-radius: 9px;
  background: var(--ground); cursor: pointer;
  transition: border-color .15s, background .15s;
}
.drop:hover { border-color: var(--accent); background: var(--accent-soft); }
/* Locked while a previewed list is on screen: the list was built from this
   file, so changing it now would put the two out of step. Not just disabled —
   the zone has to stop inviting the click as well. */
.drop.is-locked {
  cursor: default; opacity: .62; border-style: solid;
}
.drop.is-locked:hover { border-color: var(--field); background: var(--ground); }
.drop input[type=file] {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; overflow: hidden; clip: rect(0 0 0 0);
}
/* The input is visually hidden, so focus has to show on the zone itself —
   otherwise tabbing to it gives no indication at all. */
.drop:has(input[type=file]:focus-visible) {
  outline: 2px solid var(--accent); outline-offset: 2px;
  border-color: var(--accent);
}
.drop-icon { width: 26px; height: 26px; flex: none; color: var(--ink-3); }
.drop-text {
  font-size: 14px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.drop-text small {
  display: block; font-weight: 400; font-size: 12px; color: var(--ink-3); margin-top: 2px;
}
.drop.has-file { border-style: solid; border-color: var(--accent); background: var(--accent-soft); }
.drop.has-file .drop-icon { color: var(--accent); }
.icon-btn {
  background: none; border: none; color: var(--ink-3);
  font-size: 26px; line-height: 1; padding: 0 4px; cursor: pointer;
}
.icon-btn:hover { background: none; color: var(--ink); }

.confirm-scroll { max-height: 42vh; overflow-y: auto; }
#confirm { margin-top: 22px; border-top: 1px solid var(--rule); padding-top: 18px; }
#confirm table { min-width: 520px; }
#confirm h3 { margin: 0; font-size: 15px; font-weight: 700; }

@media (max-width: 640px) {
  .modal-back { padding: 0; }
  .modal { max-width: none; min-height: 100vh; max-height: none; border-radius: 0; }
  .modal-foot { border-radius: 0; }
}

/* ── confirmation panel ──────────────────────────────────── */
.confirm-head {
  display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap;
  padding: 22px 26px 18px; border-bottom: 1px solid var(--rule);
}
.confirm-head h2 { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -.01em; }
.confirm-head .hint { margin-top: 4px; }
.confirm-head > div:first-child { flex: 1; min-width: 260px; }
.confirm-actions { display: flex; gap: 10px; }
#confirm table { min-width: 640px; }
#confirm th:first-child, #confirm td:first-child { padding-left: 26px; }
#confirm th:last-child,  #confirm td:last-child  { padding-right: 26px; }
#confirm input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
tr.row-bad td { background: var(--failed-bg); }
tr.row-bad:hover td { background: var(--failed-bg); }

/* live dot on an active row */
.dot-live {
  width: 7px; height: 7px; border-radius: 50%; background: var(--processing);
  display: inline-block; margin-right: 7px; animation: pulse 1.4s ease-in-out infinite;
}
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .25 } }
@media (prefers-reduced-motion: reduce) { .dot-live { animation: none } }

/* ── login ───────────────────────────────────────────────── */
.login-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.login-card { width: 100%; max-width: 380px; }
.login-head { text-align: center; margin-bottom: 26px; }
.login-head .mark-logo {
  width: 46px; height: 46px; display: block; margin: 0 auto 16px;
}
.login-head h1 { font-size: 20px; }
.login-head p { margin: 6px 0 0; color: var(--ink-3); font-size: 13.5px; }
.login-head .by {
  margin: 2px 0 10px; font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}
.login-card button { width: 100%; justify-content: center; margin-top: 4px; }

.foot { text-align: center; color: var(--ink-3); font-size: 12px; margin-top: 22px; }
.foot a { color: var(--ink-3); }

@media (max-width: 700px) {
  .topbar-in { flex-wrap: wrap; gap: 12px; padding: 10px 16px; }
  .page { padding: 22px 16px 60px; }
}

/* ── OUES design: burgundy workspace ─────────────────────────── */
:root {
  --accent: #79211d;
  --accent-dark: #5f1714;
  --accent-soft: #fdf3f2;
  --accent-btn: #79211d;
  --ground: #f8f6f5;
  --surface: #ffffff;
  --panel: #fdf3f2;
  --rule: #e1c3c0;
  --field: #79211d;
  --ink: #000000;
  --ink-2: #3b3b3b;
  --ink-3: #666666;
  --shadow: 0 16px 36px rgba(121, 33, 29, .08);
  --radius: 18px;
}

body { background: var(--ground); color: var(--ink); overflow-x: hidden; }
.topbar { background: #082b46; border-bottom: 0; box-shadow: 0 2px 14px rgba(8, 43, 70, .16); }
.topbar-in { max-width: 1484px; min-height: 90px; padding: 0 42px; gap: 12px; }
.brand { color: #fff; font-size: 23px; gap: 14px; }
.brand-mark, .login-mark {
  width: 38px; height: 38px; display: inline-block; flex: none;
  border-radius: 11px 11px 11px 3px; background: linear-gradient(135deg, #11a5a1, #38d0c7);
}
/* A status label, not a control. Everything that made it read as a button is
   gone — no fill, no border, no pill — and what is left is the vocabulary of a
   caption: small, letter-spaced, uppercase, with a lit dot for the state it is
   reporting. The default cursor keeps the message consistent on hover. */
.secure-badge {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 0; border: 0; border-radius: 0; background: none;
  color: #e3c4c1; font-size: 11.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .09em;
  cursor: default; user-select: none;
}
.secure-badge::before {
  content: ""; flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: #35c08a; box-shadow: 0 0 0 3px rgba(53, 192, 138, .18);
}
.who { color: #c8d9e6; }
.topbar button { padding: 9px 14px; font-size: 13px; }
.topbar button.ghost { color: #d7e4ec; border-color: #37637c; }
.topbar button.ghost:hover:not(:disabled) { color: #fff; background: #164967; }
.topbar .link { color: #c8d9e6; }
.topbar .link:hover { color: #fff; }
.bar-sep { background: #37637c; }

.page { max-width: 1484px; padding: 46px 42px 86px; gap: 28px; }
.inventory-hero {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; justify-content: space-between; align-items: center; gap: 48px;
  min-height: 278px; padding: 48px;
  background: #082b46; color: #fff; border-radius: 26px;
}
.inventory-hero::after {
  content: ""; position: absolute; z-index: -1; right: -86px; bottom: -160px;
  width: 380px; height: 380px; border: 1px solid #2c8791; border-radius: 50%;
  box-shadow: 0 0 0 56px #082b46, 0 0 0 57px #2c8791;
}
.inventory-hero-copy { max-width: 780px; }
.eyebrow { margin: 0 0 18px; color: #75e6df; font-size: 14px; font-weight: 800; letter-spacing: .02em; text-transform: uppercase; }
.inventory-hero h1 { font-size: clamp(34px, 4.1vw, 54px); line-height: 1.14; letter-spacing: -.035em; max-width: 760px; }
.inventory-hero-copy > p:last-child { margin: 14px 0 0; color: #c5dceb; font-size: 20px; }
.hero-stat { min-width: 214px; padding: 8px 0 8px 48px; border-left: 2px solid #5790a4; }
.hero-stat strong { display: block; color: #fff; font-size: 50px; line-height: 1; letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.hero-stat span { display: block; margin-top: 12px; color: #c5dceb; font-size: 16px; }

.metric-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; }
.metric-card { min-height: 176px; padding: 30px 28px; border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow); }
.metric-card > span { display: block; color: var(--ink-2); font-weight: 800; letter-spacing: .02em; text-transform: uppercase; font-size: 13px; }
.metric-card strong { display: block; margin-top: 20px; color: var(--ink); font-size: 40px; line-height: 1; letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.metric-card small { display: block; margin-top: 12px; color: var(--ink-2); font-size: 14px; }
.inventories-intro h2 { margin: 0; color: var(--ink); font-size: 31px; letter-spacing: -.025em; }
.inventories-intro .sub { margin-top: 4px; color: var(--ink-2); }

#batches { gap: 18px; }
.batch, .card { border: 0; box-shadow: var(--shadow); border-radius: var(--radius); }
.batch-head { padding: 28px 32px; }
.batch-head:hover { background: #f7fbfc; }
.batch-title { color: var(--ink); font-size: 19px; }
.batch-title small, .batch-count, .batch-pages small { color: var(--ink-2); }
.batch-pages { color: var(--ink); font-size: 23px; }
.batch-actions .btn { min-width: 128px; justify-content: center; background: var(--accent-btn); border-radius: 10px; }
.empty { padding: 54px 20px; color: var(--ink-2); }

.modal-back { background: rgba(4, 25, 42, .64); }
.modal { border: 0; border-radius: 20px; }
.modal-head { padding: 22px 24px; }
.modal-head h2 { color: var(--ink); font-size: 20px; }
.modal-body { padding: 22px 24px; }
.modal-foot { padding: 16px 24px; background: #f6fafb; border-radius: 0 0 20px 20px; }
.drop { background: #f7fbfc; border-color: #8cabb9; }
.drop:hover, .drop.has-file { background: #e8f7f5; border-color: var(--accent); }

body.login-page { background: #082b46; }
.login-page .login-wrap { min-height: 100vh; display: grid; grid-template-columns: minmax(0, 57%) minmax(430px, 43%); padding: 0; }
.login-story { position: relative; overflow: hidden; display: flex; flex-direction: column; padding: 54px 11vw 58px 7vw; color: #fff; }
.login-story::after { content: ""; position: absolute; right: -186px; bottom: -210px; width: 470px; height: 470px; border: 1px solid #2c8791; border-radius: 50%; box-shadow: 0 0 0 64px #082b46, 0 0 0 65px #2c8791; }
.login-brand { display: inline-flex; align-items: center; gap: 15px; color: #fff; text-decoration: none; font-size: 28px; font-weight: 800; }
.login-story-copy { margin: auto 0 52px; max-width: 575px; }
.login-story-copy .eyebrow { margin-bottom: 32px; }
.login-story h1 { font-size: clamp(43px, 5vw, 67px); line-height: 1.12; letter-spacing: -.045em; }
.login-story-copy > p:last-child { margin: 26px 0 0; color: #cae0ec; font-size: 24px; line-height: 1.62; }
.login-benefits { position: relative; z-index: 1; display: grid; gap: 20px; margin: 0; padding: 0; list-style: none; color: #d8ebf4; font-size: 18px; }
.login-benefits li::before { content: ""; display: inline-block; width: 14px; height: 14px; margin-right: 18px; border: 1px solid #2c8791; border-radius: 50%; background: #114a63; vertical-align: -1px; }
.login-main { display: flex; align-items: center; justify-content: center; padding: 48px 8vw; background: #f3f8fa; }
.login-card { width: min(100%, 490px); }
.login-head { margin: 0 0 26px; text-align: left; }
.login-head .login-mark { margin-bottom: 28px; }
.login-head h1 { color: var(--ink); font-size: 32px; letter-spacing: -.03em; }
.login-head p { color: var(--ink-2); font-size: 18px; }
.login-card .card { padding: 0; box-shadow: none; background: transparent; }
.login-card label { color: var(--ink); font-size: 15px; }
.login-card input[type=text], .login-card input[type=email],
.login-card input[type=password] { padding: 15px 16px; background: #fff; border-radius: 10px; }
.login-card button { margin-top: 14px; min-height: 58px; border-radius: 10px; font-size: 17px; }
.login-card .foot { margin-top: 26px; text-align: left; color: var(--ink-2); }

@media (max-width: 980px) {
  .metric-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .login-page .login-wrap { grid-template-columns: 1fr; }
  .login-story { min-height: 420px; padding: 42px 10vw; }
  .login-story-copy { margin: 72px 0 32px; }
  .login-main { padding: 56px 10vw; }
}
@media (max-width: 720px) {
  .topbar-in { min-height: 78px; padding: 12px 20px; }
  .brand { font-size: 18px; }
  .secure-badge, .topbar #clear-all, .topbar .bar-sep { display: none; }
  .topbar .who { margin-left: auto; }
  .page { padding: 24px 20px 60px; gap: 20px; }
  .inventory-hero { min-height: 0; padding: 30px 26px; }
  .inventory-hero h1 { font-size: 35px; }
  .inventory-hero-copy > p:last-child { font-size: 16px; }
  .hero-stat { min-width: 125px; padding-left: 24px; }
  .hero-stat strong { font-size: 34px; }
  .hero-stat span { font-size: 13px; }
  .metric-grid { gap: 14px; }
  .metric-card { min-height: 142px; padding: 22px 20px; }
  .metric-card strong { font-size: 33px; }
  .batch-head { padding: 20px; }
  .login-story { min-height: 390px; padding: 32px 28px; }
  .login-brand { font-size: 24px; }
  .login-story-copy { margin-top: 52px; }
  .login-story h1 { font-size: 42px; }
  .login-story-copy > p:last-child { font-size: 18px; }
  .login-benefits { font-size: 15px; }
  .login-main { padding: 44px 28px; }
}
@media (max-width: 520px) {
  .metric-grid { grid-template-columns: 1fr; }
  .inventory-hero { flex-direction: column; align-items: flex-start; gap: 26px; }
  .hero-stat { border-left: 0; border-top: 2px solid #5790a4; padding: 20px 0 0; }
  .login-story { min-height: 0; }
  .login-benefits { display: none; }
}

/* ── OUES sign-in branding ─────────────────────────────────── */
body.login-page { background: #79211d; }
.login-page .login-story { background: #79211d; }
.login-page .login-story::after {
  border-color: rgba(255, 255, 255, .34);
  box-shadow: 0 0 0 64px #79211d, 0 0 0 65px rgba(255, 255, 255, .34);
}
.login-page .login-brand { width: 100%; gap: 10px; }
.login-page .ous-logo {
  display: block; width: 110px; height: 54px; object-fit: contain;
  object-position: left center;
}
.login-page .login-brand-title { color: #fff; font-size: 22px; line-height: 1.1; white-space: nowrap; }
/* Same label, same fix as .secure-badge in the topbar: a bordered pill beside
   a sign-in button is read as a second button. Caption vocabulary instead. */
.login-page .login-security {
  margin-left: auto; padding: 0; border: 0; border-radius: 0; background: none;
  display: inline-flex; align-items: center; gap: 7px;
  color: rgba(255, 255, 255, .82); font-size: 11.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .09em;
  white-space: nowrap; cursor: default; user-select: none;
}
.login-page .login-security::before {
  content: ""; flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: #35c08a; box-shadow: 0 0 0 3px rgba(53, 192, 138, .2);
}
.login-page .eyebrow { color: #fff; }
.login-page .login-story h1,
.login-page .login-story-copy > p:last-child,
.login-page .login-benefits { color: #fff; }
.login-page .login-benefits li::before { border-color: rgba(255, 255, 255, .8); background: #79211d; }
.login-page .login-main { background: #f8f6f5; }
.login-page .login-head h1,
.login-page .login-head p,
.login-page .login-card label,
.login-page .login-card .foot { color: #000; }
.login-page .login-card input[type=text],
.login-page .login-card input[type=email],
.login-page .login-card input[type=password] { border-color: #79211d; color: #000; }
.login-page .login-card input:focus { border-color: #79211d; box-shadow: 0 0 0 3px rgba(121, 33, 29, .18); }
.login-page .login-card button { background: #79211d; color: #fff; }
.login-page .login-card button:hover:not(:disabled) { background: #5f1714; }

@media (max-width: 720px) {
  .login-page .ous-logo { width: 88px; height: 44px; }
  .login-page .login-brand-title { font-size: 17px; }
  .login-page .login-security { display: none; }
}

/* Reference-matched OUES sign-in composition. */
.login-page .login-wrap {
  display: grid; grid-template-columns: minmax(0, 60%) minmax(390px, 40%);
  grid-template-rows: 61px minmax(0, 1fr);
  height: 100vh; min-height: 0;
}
.login-page .login-header {
  grid-column: 1 / -1; display: flex; align-items: center; gap: 24px;
  min-height: 61px; padding: 0 14px; background: #79211d; color: #fff;
}
.login-page .login-header .login-brand { width: auto; display: inline-flex; align-items: center; }
.login-page .login-header .ous-logo { width: 100px; height: 50px; object-fit: contain; }
.login-page .login-header .brand-divider { width: 1px; height: 40px; margin: 0 14px; background: rgba(255,255,255,.82); }
.login-page .login-header .login-brand-title {
  color: #fff; font-size: 20px; font-weight: 800; letter-spacing: .01em;
  text-transform: uppercase; white-space: nowrap;
}
.login-page .login-header .login-security {
  display: inline-flex; margin: 0 0 0 auto; padding: 0;
  border: 0; border-radius: 0; background: none;
  color: rgba(255, 255, 255, .82); font-size: 12px; font-weight: 600;
}
.login-page .login-story {
  grid-column: 1; grid-row: 2; min-height: 0; padding: 0;
  align-self: stretch; height: 100%;
  background: linear-gradient(rgba(55, 14, 13, .30), rgba(55, 14, 13, .40)),
              url("img/login-background.jpg") center / cover no-repeat;
}
.login-page .login-story::after { display: none; }
.login-page .login-story-copy {
  position: relative; z-index: 1; margin: 0; max-width: 860px; padding: clamp(76px, 13vh, 170px) clamp(42px, 6.5vw, 96px) 0;
}
.login-page .login-story h1 { color: #fff; font-size: clamp(42px, 4.4vw, 65px); line-height: 1.1; max-width: 790px; }
.login-page .login-story-copy > p:last-child { max-width: 820px; margin-top: 18px; color: #fff; font-size: clamp(18px, 1.55vw, 23px); font-weight: 600; line-height: 1.3; }
.login-page .login-benefits { position: relative; z-index: 1; gap: 1px; margin: 24px clamp(42px, 6.5vw, 96px) 0; color: #fff; font-size: clamp(16px, 1.35vw, 21px); font-weight: 600; }
.login-page .login-benefits li::before { display: none; }
.login-page .login-main {
  grid-column: 2; grid-row: 2; min-height: 0; justify-content: flex-start;
  align-self: stretch; height: 100%; overflow-y: auto;
  padding: clamp(26px, 4vw, 58px) clamp(36px, 3.5vw, 62px); background: #f5f8fa;
}
.login-page .login-card { width: min(100%, 410px); padding-top: 22px; }
.login-page .login-head { margin: 0 0 34px; }
.login-page .form-logo { display: block; width: 120px; height: 64px; margin: 0 0 18px; object-fit: contain; object-position: left center; }
.login-page .login-head h1 { font-size: 30px; line-height: 1.32; max-width: 320px; }
.login-page .login-head p { margin-top: 12px; color: #4d7193; font-size: 18px; }
.login-page .login-card .field { gap: 8px; margin-bottom: 22px; }
.login-page .login-card label { font-size: 15px; font-weight: 800; }
.login-page .login-card input[type=text],
.login-page .login-card input[type=email],
.login-page .login-card input[type=password] { min-height: 57px; padding: 13px 15px; border: 1px solid #9bb7ca; }
.login-page .login-card button { min-height: 64px; margin-top: 6px; font-size: 17px; font-weight: 800; letter-spacing: .01em; }
.login-page .login-card .foot { margin-top: 28px; color: #4d7193; font-size: 14px; }

@media (max-width: 960px) {
  .login-page .login-wrap { display: block; height: auto; min-height: 100vh; }
  .login-page .login-story { min-height: 360px; }
  .login-page .login-main { min-height: auto; padding: 42px 10vw; }
  .login-page .login-header .login-brand-title { font-size: 17px; }
  .login-page .login-story-copy { padding-left: 42px; padding-right: 42px; }
  .login-page .login-benefits { margin-left: 42px; margin-right: 42px; }
}
@media (max-width: 760px) {
  .login-page .login-wrap { display: block; min-height: 100vh; }
  .login-page .login-header { min-height: 64px; padding: 7px 14px; }
  .login-page .login-header .ous-logo { width: 78px; height: 42px;}
  .login-page .login-header .brand-divider { height: 31px; margin: 0 10px; }
  .login-page .login-header .login-brand-title { font-size: 14px; }
  .login-page .login-header .login-security { font-size: 12px; padding: 7px 9px; }
  .login-page .login-story { min-height: 360px; }
  .login-page .login-story-copy { padding: 64px 28px 0; }
  .login-page .login-story h1 { font-size: 40px; }
  .login-page .login-benefits { margin: 20px 28px 0; }
  .login-page .login-main { padding: 42px 28px; }
}

/* Desktop layout: 60% visual panel and 40% sign-in panel. */
@media (min-width: 761px) {
  .login-page .login-wrap { grid-template-columns: 60% 40%; }
}

/* ── OUES burgundy theme for the New Report dialog ─────────── */
#modal .modal-head { background: #fff; border-top: 5px solid #79211d; }
#modal .modal-eyebrow {
  margin: 0 0 4px; color: #79211d; font-size: 12px; font-weight: 800;
  letter-spacing: .07em; text-transform: uppercase;
}
#modal .modal-head h2 { color: #000; }
#modal .modal-head .hint { color: #000; }
#modal .modes .mode { background: #fff; color: #000; }
#modal .modes .mode small { color: #000; }
#modal .modes .mode:hover {
  border-color: #79211d; background: #fdf3f2;
}
#modal .modes .mode[aria-selected="true"] {
  border-color: #79211d; background: #fdf3f2;
  box-shadow: 0 0 0 1px #79211d inset;
}
#modal .modes .mode[aria-selected="true"] small { color: #79211d; }
#modal .modal-body label, #modal .modal-body .hint, #modal .modal-body .pane-hint { color: #000; }
#modal .modal-body input[type=text], #modal .modal-body input[type=url], #modal .modal-body input[type=file] { border-color: #79211d; color: #000; }
#modal .modal-body input:focus { border-color: #79211d; box-shadow: 0 0 0 3px rgba(121, 33, 29, .16); }
#modal .drop { border-color: #79211d; background: #fdf3f2; }
#modal .drop:hover, #modal .drop.has-file { border-color: #79211d; background: #fae8e6; }
#modal #submit-btn, #modal #go { background: #79211d; color: #fff; }
#modal #submit-btn:hover:not(:disabled), #modal #go:hover:not(:disabled) { background: #79211d; }
#modal .msg.ok { background: #fdf0ef; color: #79211d; border-left-color: #79211d; }
#modal .pill.COMPLETED, .pill.COMPLETED { background: #79211d; color: #fff; }
#modal .icon-btn, #files-modal .icon-btn { color: #000; }
#modal .icon-btn:hover, #files-modal .icon-btn:hover {
  background: #79211d; border-radius: 5px; color: #fff;
}

/* ── OUES burgundy theme for the Accessibility Remediation workspace ── */
body:not(.login-page), .page { background: #f8f6f5; }
.topbar {
  background: #79211d;
  box-shadow: 0 2px 14px rgba(121, 33, 29, .2);
}
.topbar .brand { gap: 0; color: #fff; }
.topbar .workspace-logo {
  display: block; width: 100px; height: 50px; object-fit: contain;
  object-position: left center;
}
.topbar .workspace-divider {
  width: 1px; height: 40px; margin: 0 18px; background: rgba(255, 255, 255, .82);
}
.topbar .workspace-title { color: #fff; font-size: 20px; font-weight: 800; letter-spacing: .01em; }
.topbar .secure-badge { background: none; border: 0; color: #e3c4c1; }
.topbar .who, .topbar .link { color: #fff; }
.topbar .bar-sep { background: rgba(255, 255, 255, .45); }
.topbar #add-job { background: #fff; color: #79211d; }
.topbar #add-job:hover:not(:disabled) { background: #fff; color: #79211d; }
.topbar button.ghost { color: #fff; border-color: rgba(255, 255, 255, .55); }
.topbar button.ghost:hover:not(:disabled), .topbar .link:hover { background: rgba(255, 255, 255, .12); color: #fff; }

.inventory-hero {
  min-height: 120px; padding: 16px 24px; gap: 28px;
  background: #79211d; color: #fff; border-top: 5px solid #79211d;
}
.inventory-hero::after { border-color: rgba(255, 255, 255, .35); box-shadow: 0 0 0 56px #79211d, 0 0 0 57px rgba(255, 255, 255, .35); }
.inventory-hero .eyebrow {
  display: inline-block; padding: 0; border-radius: 0;
  background: transparent; color: #fff;
}
.inventory-hero h1, .inventory-hero-copy > p:last-child { color: #fff; }
.inventory-hero h1 { font-size: clamp(26px, 3vw, 38px); }
.inventory-hero-copy > p:last-child { margin-top: 8px; font-size: 16px; }
.hero-stat { border-left-color: rgba(255, 255, 255, .6); }
.hero-stat { min-width: 160px; padding-left: 24px; }
.hero-stat strong { color: #fff; font-size: 36px; }
.hero-stat span { margin-top: 6px; color: #fff; font-size: 14px; }
.metric-card strong { color: #79211d; }
.inventories-intro {
  display: grid; grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline; column-gap: 20px; min-width: 0;
}
.inventories-intro h2 { flex: none; color: #79211d; font-size: 28px; }
.inventories-intro .sub {
  width: max-content; max-width: none; min-width: 0; margin: 0; overflow: visible;
  justify-self: end; text-align: right; text-overflow: clip; white-space: nowrap; letter-spacing: -.015em;
  font-size: clamp(10px, .92vw, 13px);
}
.inventories-intro, #batches, .batch { background: #f8f6f5; }
.batch { border: 1px solid #79211d; }

/* The report table has a fixed column map, so every value forms a clean grid. */
.batch-body table { width: 100%; min-width: 1160px; table-layout: fixed; }
.batch-body th, .batch-body td { vertical-align: middle; }
.batch-body th:nth-child(1), .batch-body td:nth-child(1) { width: 52px; }
.batch-body th:nth-child(2), .batch-body td:nth-child(2) { width: 24%; }
.batch-body th:nth-child(3), .batch-body td:nth-child(3) { width: 9%; }
.batch-body th:nth-child(5), .batch-body td:nth-child(5),
.batch-body th:nth-child(6), .batch-body td:nth-child(6),
.batch-body th:nth-child(7), .batch-body td:nth-child(7),
.batch-body th:nth-child(8), .batch-body td:nth-child(8) { width: 52px; }
.batch-body th:nth-child(9), .batch-body td:nth-child(9) { width: 76px; }
.batch-body th:nth-child(10), .batch-body td:nth-child(10) { width: 92px; }
.batch-body th:nth-child(11), .batch-body td:nth-child(11) { width: 142px; }
.batch-body .course, .batch-body .stage { min-width: 0; }
.batch-body .course-name, .batch-body .stage {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Keep the information in every inventory card on the same visual columns. */
@media (min-width: 1150px) {
  .batch-head {
    display: grid;
    grid-template-columns: 16px minmax(0, 1fr) 130px 96px 94px 192px;
    align-items: center;
    column-gap: 16px;
  }
  .batch-title { grid-column: 2; min-width: 0; }
  .batch-head > .pill { grid-column: 3; justify-self: center; }
  .batch-count { grid-column: 4; justify-self: start; }
  .batch-pages { grid-column: 5; justify-self: end; }
  .batch-actions { grid-column: 6; justify-self: end; width: 100%; }
  .batch-actions .btn { width: 100%; }
}
.batch-actions .btn, button.retry { border-color: #79211d; color: #79211d; }
.batch-actions .btn { background: #fdf3f2; color: #000; }
.batch-actions .btn:hover:not(:disabled) { background: #fdf3f2; color: #000; }
.row-actions a.btn,
#files-download,
.zip-sel:not(:disabled) {
  background: #fdf3f2; border-color: #79211d; color: #000;
}
.row-actions a.btn:hover,
#files-download:hover,
.zip-sel:not(:disabled):hover { background: #fdf3f2; color: #000; }
button.retry:hover:not(:disabled) { background: #fdf3f2; color: #79211d; }
.batch-body tbody tr:hover td,
.batch-body tr.clickable:hover td { background: #fdf3f2; color: #000; }

@media (max-width: 720px) {
  .inventory-hero { min-height: 0; padding: 16px 20px; gap: 18px; }
  .inventory-hero h1 { font-size: 28px; }
  .inventory-hero-copy > p:last-child { font-size: 14px; }
  .inventories-intro { grid-template-columns: auto minmax(0, 1fr); align-items: baseline; column-gap: 12px; }
  .inventories-intro .sub { text-align: right; }
  .topbar .workspace-logo { width: 78px; height: 42px; }
  .topbar .workspace-divider { height: 31px; margin: 0 10px; }
  .topbar .workspace-title { font-size: 14px; }
}

/* ── primary navigation ────────────────────────────────────────
   Sits in the bar beside the workspace title. The logo, divider, title and
   Secure Workspace label are untouched; the nav took over New Inventory and
   Sign out, which used to be buttons on the right, so the same action is not
   offered twice a few inches apart. */
.primary-nav {
  display: flex; align-items: center; gap: 4px;
  margin-left: 26px; flex: none;
}
.nav-link {
  position: relative;
  display: inline-flex; align-items: center;
  padding: 9px 14px 10px;
  border: 0; border-radius: 8px 8px 0 0; background: none;
  color: #fff; font: inherit; font-size: 14px; font-weight: 600;
  line-height: 1.2; text-decoration: none; white-space: nowrap;
  cursor: pointer; transition: background .15s;
}
/* A lighter maroon rather than a white wash: the bar is the brand colour, and
   a translucent white film on it greys the label it is meant to highlight.
   White on #93332e is 7.6:1, so the text is if anything easier to read. */
.nav-link:hover, .nav-link:focus-visible { background: #93332e; color: #fff; }

/* Hidden until the bar runs out of room. */
/* Sign out, sitting beside the identity in the bar rather than in the nav.
   Deliberately not .nav-link: that class is a tab in the nav row, with a
   top-only radius and a narrow-screen rule that restyles it for the dropdown
   panel. This one is a button in the bar at every width. */
.signout-btn {
  display: inline-flex; align-items: center;
  padding: 7px 13px;
  border: 1px solid rgba(255, 255, 255, .38); border-radius: 8px;
  background: none; color: #fff;
  font: inherit; font-size: 13px; font-weight: 600; line-height: 1.2;
  white-space: nowrap; cursor: pointer;
  transition: background .15s, border-color .15s;
}
.signout-btn:hover, .signout-btn:focus-visible {
  background: #93332e; border-color: rgba(255, 255, 255, .7);
}

.nav-toggle {
  display: none;
  padding: 0; width: 42px; height: 42px; flex: none;
  align-items: center; justify-content: center;
  border: 1px solid rgba(255, 255, 255, .5); border-radius: 9px;
  background: none; cursor: pointer;
}
.nav-toggle:hover:not(:disabled) { background: #93332e; }
/* Three bars from one element: the middle is the box, the outer two are its
   pseudo-elements, so the glyph costs no markup and no request. */
.nav-bars, .nav-bars::before, .nav-bars::after {
  display: block; width: 20px; height: 2px; border-radius: 2px; background: #fff;
}
.nav-bars { position: relative; }
.nav-bars::before, .nav-bars::after { content: ""; position: absolute; left: 0; }
.nav-bars::before { top: -6px; }
.nav-bars::after  { top: 6px; }
#nav-toggle[aria-expanded="true"] { background: #93332e; }

@media (max-width: 980px) {
  /* Same markup, different shape: the nav drops out of the bar and becomes a
     panel under it. Nothing is duplicated for small screens, so the items and
     their active state cannot drift apart between two menus. */
  .nav-toggle { display: inline-flex; }
  .primary-nav {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0;
    margin: 0; padding: 8px;
    flex-direction: column; align-items: stretch; gap: 2px;
    background: #79211d; border-top: 1px solid rgba(255, 255, 255, .22);
    box-shadow: 0 14px 26px rgba(121, 33, 29, .28);
    z-index: 30;
  }
  .primary-nav.is-open { display: flex; }
  .nav-link {
    justify-content: flex-start;
    padding: 13px 14px; border-radius: 8px; font-size: 15px;
  }
}

/* ── Create account, from the login card ──────────────────────
   A quiet line under the form: signing in is what nearly every visit is for,
   and creating an account happens once. */
.signup-line {
  text-align: center; margin: 16px 0 0;
  font-size: 13px; color: var(--ink-3);
}
.signup-line .link {
  padding: 0; font-size: 13px; font-weight: 650;
  color: var(--accent-dark); width: auto;
}
.signup-line .link:hover { color: var(--accent); text-decoration: underline; }

/* The token field and its Verify button share a line, because the button acts
   on that field and nothing else. */
.verify-row { display: flex; gap: 8px; align-items: stretch; }
.verify-row input { flex: 1; min-width: 0; }
.verify-row button { flex: none; white-space: nowrap; }

/* What Canvas said about the token, in the four states it can be in. Carries an
   icon as well as a colour so it does not rely on colour alone. */
.verify-state {
  font-size: 12px; font-weight: 650; margin-top: 2px;
  display: inline-flex; align-items: center; gap: 5px;
}
.verify-state::before { font-weight: 700; }
.verify-state[data-state="idle"]  { color: var(--ink-3); font-weight: 400; }
.verify-state[data-state="idle"]::before  { content: "—"; }
.verify-state[data-state="busy"]  { color: var(--accent-dark); }
.verify-state[data-state="busy"]::before  { content: "…"; }
.verify-state[data-state="ok"]    { color: var(--completed); }
.verify-state[data-state="ok"]::before    { content: "✓"; }
.verify-state[data-state="bad"]   { color: var(--failed); }
.verify-state[data-state="bad"]::before   { content: "✕"; }

/* 'Canvas access token' beside the Bearer ID label: the field is called one
   thing in this workspace and another in Canvas, and somebody hunting for it
   needs the Canvas name. */
.req-note {
  font-weight: 400; font-size: 11.5px; color: var(--ink-3);
  margin-left: 6px;
}

/* Who is signed in, in the jobs header. The admin chip is a chip rather than
   a word in the name, so it reads as a role and not as part of the person. */
.who-admin {
  margin-left: 6px; padding: 1px 6px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; vertical-align: 1px;
  border: 1px solid currentColor;
}

/* The login card's own buttons stretch; the dialog's sit in a footer row and
   must not. */
.modal-foot button { width: auto; margin-top: 0; }

/* The Create Account dialog wears the same burgundy head as the New Report
   dialog. The eyebrow rule above is scoped to #modal, so the login page needs
   its own — one place, not a copy of the whole block. */
#signup-modal .modal-head { background: #fff; border-top: 5px solid #79211d; }
#signup-modal .modal-eyebrow {
  margin: 0 0 4px; color: #79211d; font-size: 12px; font-weight: 800;
  letter-spacing: .07em; text-transform: uppercase;
}
#signup-modal .modal-head h2 { color: #000; }
#signup-modal .modal-head .hint { color: #000; }
#signup-modal .icon-btn { color: #000; }

/* The login page paints every button in the card burgundy and 64px tall
   (.login-page .login-card button, above). The create-account line is a
   sentence with a link in it, not a call to action, so it opts out at the same
   specificity — anything less loses to that rule. */
.login-page .login-card .signup-line .link {
  background: none; border: none; box-shadow: none;
  color: #79211d; width: auto; min-height: 0;
  margin: 0; padding: 0 2px;
  font-size: 14px; font-weight: 800; letter-spacing: 0;
  text-transform: none; display: inline;
}
.login-page .login-card .signup-line .link:hover:not(:disabled) {
  background: none; color: #5f1714; text-decoration: underline;
}

/* ── password requirements, as a live checklist ────────────────
   Two columns, because five items in one column pushes the token field and the
   footer out of a short dialog. A met rule earns a tick and loses its emphasis:
   the eye should land on what is still outstanding, not on what is done. */
.pw-rules {
  list-style: none; margin: 4px 0 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px 10px;
}
.pw-rules li {
  font-size: 11.5px; line-height: 1.5; color: var(--ink-3);
  display: flex; align-items: center; gap: 5px;
}
.pw-rules li::before {
  content: "•"; font-weight: 700; width: 9px; text-align: center;
  color: var(--ink-3);
}
.pw-rules li[data-met="yes"] { color: var(--completed); }
.pw-rules li[data-met="yes"]::before { content: "✓"; color: var(--completed); }
.pw-rules li[data-met="no"] { color: var(--ink-2); }
@media (max-width: 480px) { .pw-rules { grid-template-columns: 1fr; } }
