/* MHStudy portal — the design system, entirely self-contained: no build step, no CDN, no
   external font. A portal that fetched a stylesheet or a typeface from the internet would tell a
   third party which machines on this LAN are looking at an unpublished submission.

   Direction: Swiss / International Typographic. The grid is the design; hairlines instead of
   shadows; typographic contrast carries the hierarchy. Navy titles, teal and orange accents and
   an off-white page, so the portal reads as the same project as the meeting deck.

   Everything below is driven by the tokens in `:root`. Dark mode redefines the tokens and
   nothing else — there is no second stylesheet and no inverted colour anywhere. */

:root {
  /* ── palette ─────────────────────────────────────────────────────────────── */
  --ink:        #14304A;   /* navy: headings and primary text */
  --ink-soft:   #5A6B78;   /* secondary text, labels */
  --teal:       #177E70;   /* "good" / model accent, primary section colour */
  --orange:     #C97B22;   /* human action / attention */
  --red:        #B03A2E;   /* mandatory stop, errors */
  --paper:      #F7F8FA;   /* page background */
  --surface:    #FFFFFF;
  --rule:       #DDE3E8;   /* hairlines */
  --focus:      #177E70;

  /* Washes: the same hues at panel strength. Explicit rather than `color-mix`, so the render is
     identical on every engine that will ever open this LAN page. */
  --teal-wash:   #E7F1EF;
  --orange-wash: #F8EEE0;
  --red-wash:    #F7E8E6;
  --ink-wash:    #E9EEF3;
  --ink-line:    #BCC9D5;

  /* ── type ────────────────────────────────────────────────────────────────── */
  --serif: "Iowan Old Style", Charter, "Bitstream Charter", "Palatino Linotype", Palatino,
           Georgia, serif;
  --sans:  -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --mono:  ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;

  --t-h1: 2.25rem;
  --t-h2: 1.35rem;
  --t-body: 1rem;
  --t-small: .875rem;
  --t-caption: .8rem;

  /* ── spacing, 4px base ───────────────────────────────────────────────────── */
  --s1: .25rem;
  --s2: .5rem;
  --s3: .75rem;
  --s4: 1rem;
  --s6: 1.5rem;
  --s8: 2rem;
  --s12: 3rem;

  --speed: .18s;
}

/* Dark is a cool slate, never an inversion. Declared as a media query for the reader's own
   setting, then re-declared under `[data-theme]` so the toggle wins in BOTH directions: the
   attribute selector outspecifies bare `:root` whatever the source order. */
@media (prefers-color-scheme: dark) {
  :root {
    --ink:        #E3E8EC;
    --ink-soft:   #9BAAB6;
    --teal:       #4FBFAC;
    --orange:     #E5A25A;
    --red:        #E0776A;
    --paper:      #131A20;
    --surface:    #1A232B;
    --rule:       #2A3742;
    --focus:      #4FBFAC;

    --teal-wash:   #16302C;
    --orange-wash: #33271A;
    --red-wash:    #331F1D;
    --ink-wash:    #212C36;
    --ink-line:    #3B4B59;
  }
}

:root[data-theme="dark"] {
  --ink:        #E3E8EC;
  --ink-soft:   #9BAAB6;
  --teal:       #4FBFAC;
  --orange:     #E5A25A;
  --red:        #E0776A;
  --paper:      #131A20;
  --surface:    #1A232B;
  --rule:       #2A3742;
  --focus:      #4FBFAC;

  --teal-wash:   #16302C;
  --orange-wash: #33271A;
  --red-wash:    #331F1D;
  --ink-wash:    #212C36;
  --ink-line:    #3B4B59;
}

:root[data-theme="light"] {
  --ink:        #14304A;
  --ink-soft:   #5A6B78;
  --teal:       #177E70;
  --orange:     #C97B22;
  --red:        #B03A2E;
  --paper:      #F7F8FA;
  --surface:    #FFFFFF;
  --rule:       #DDE3E8;
  --focus:      #177E70;

  --teal-wash:   #E7F1EF;
  --orange-wash: #F8EEE0;
  --red-wash:    #F7E8E6;
  --ink-wash:    #E9EEF3;
  --ink-line:    #BCC9D5;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.65;
}

/* ── page frame ─────────────────────────────────────────────────────────────── */

.masthead {
  border-bottom: 1px solid var(--rule);
  background: var(--surface);
}

.masthead-inner {
  max-width: 46rem;
  margin: 0 auto;
  padding: var(--s3) var(--s4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
}

body.is-wide .masthead-inner { max-width: 82rem; }

.wordmark {
  font-family: var(--serif);
  font-size: 1.05rem;
  letter-spacing: .01em;
  color: var(--ink);
  text-decoration: none;
}

.wordmark b { font-weight: 600; }
.wordmark span { color: var(--ink-soft); font-weight: 400; }

.theme-toggle {
  min-height: 44px;
  padding: var(--s1) var(--s3);
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--t-caption);
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--speed) linear, border-color var(--speed) linear;
}

/* `background` is restated because the generic `button:hover` rule below would otherwise fill
   this one in too — it is a quiet control in the header, not a call to action. */
.theme-toggle:hover {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink-line);
}

main {
  flex: 1;
  width: 100%;
  max-width: 46rem;
  margin: 0 auto;
  padding: var(--s8) var(--s4) var(--s12);
}

/* The administrator's queue is a ten-column table with the action buttons on the right; inside
   the reading column they land off-screen and `approve` cannot be clicked. */
main.wide { max-width: 82rem; }

.pagefoot {
  border-top: 1px solid var(--rule);
  background: var(--surface);
  color: var(--ink-soft);
  font-size: var(--t-caption);
}

.pagefoot p {
  max-width: 46rem;
  margin: 0 auto;
  padding: var(--s3) var(--s4);
  letter-spacing: .02em;
}

body.is-wide .pagefoot p { max-width: 82rem; }

/* ── typography ─────────────────────────────────────────────────────────────── */

h1 {
  font-family: var(--serif);
  font-size: 1.75rem;
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: -.01em;
  margin: 0 0 var(--s6);
  padding-bottom: var(--s3);
  border-bottom: 2px solid var(--ink);
}

@media (min-width: 40rem) {
  h1 { font-size: var(--t-h1); }
}

h2 {
  font-family: var(--serif);
  font-size: var(--t-h2);
  line-height: 1.25;
  font-weight: 600;
  margin: var(--s8) 0 var(--s3);
}

section > h2:first-child { margin-top: 0; }

p { margin: 0 0 var(--s4); max-width: 68ch; }
p:last-child { margin-bottom: 0; }

a { color: var(--teal); text-underline-offset: .15em; }
a:hover { color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.small { font-size: var(--t-small); color: var(--ink-soft); }

/* ── panels ─────────────────────────────────────────────────────────────────── */

section.privacy,
section.companion,
section.reason,
section.result,
section.files,
section.stages {
  background: var(--surface);
  border: 1px solid var(--rule);
  padding: var(--s4) var(--s6) var(--s6);
  margin: 0 0 var(--s6);
}

section.privacy { border-left: 3px solid var(--teal); }
section.companion { border-left: 3px solid var(--orange); }
/* Orange asks for something; red says it stopped. The rule follows the state, not the section. */
section.reason { border-left: 3px solid var(--orange); }
section.reason.reason--stop { border-left-color: var(--red); }
section.stages { border-left: 3px solid var(--ink); }
section.result { border-left: 3px solid var(--teal); }

section.privacy ul {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--t-small);
}

section.privacy li {
  position: relative;
  padding: var(--s2) 0 var(--s2) var(--s6);
  border-top: 1px solid var(--rule);
  max-width: 68ch;
}

section.privacy li:first-child { border-top: 0; }

section.privacy li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.05rem;
  width: var(--s3);
  height: 1px;
  background: var(--teal);
}

/* ── notes ──────────────────────────────────────────────────────────────────── */

p.private, p.pending, p.bookmark, p.warning, p.notice, p.refresh-note {
  border-left: 3px solid var(--rule);
  padding: var(--s3) var(--s4);
  margin: 0 0 var(--s6);
  max-width: none;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: var(--t-small);
}

p.private { border-left-color: var(--teal); color: var(--ink); background: var(--teal-wash); }
p.warning { border-left-color: var(--red); background: var(--red-wash); color: var(--ink); }
p.notice { border-left-color: var(--ink); color: var(--ink); background: var(--ink-wash); }

p.refresh-note {
  border-left: 0;
  background: transparent;
  padding: 0;
  font-size: var(--t-caption);
  letter-spacing: .02em;
}

p.error {
  border-left: 3px solid var(--red);
  background: var(--red-wash);
  color: var(--ink);
  padding: var(--s3) var(--s4);
  margin: 0 0 var(--s6);
  font-weight: 600;
  font-size: var(--t-small);
}

/* ── status chips ───────────────────────────────────────────────────────────── */

.chip {
  display: inline-block;
  padding: .15rem var(--s2);
  border: 1px solid var(--ink-line);
  border-radius: 2px;
  background: var(--ink-wash);
  color: var(--ink);
  font-size: var(--t-caption);
  line-height: 1.5;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* A full-strength navy edge, not the hairline the neutral chip uses: `en file` and `en cours`
   are the two states a supervisor most often compares, and a difference in text colour alone is
   not one you see across a room. */
.chip--run { border-color: var(--ink); background: var(--ink-wash); color: var(--ink); }
.chip--wait { border-color: var(--orange); background: var(--orange-wash); color: var(--orange); }
.chip--wait-hold { border-style: dashed; }
.chip--good { border-color: var(--teal); background: var(--teal-wash); color: var(--teal); }
.chip--done { border-color: var(--teal); background: var(--teal); color: var(--surface); }
.chip--stop { border-color: var(--red); background: var(--red-wash); color: var(--red); }
.chip--idle { color: var(--ink-soft); }

.chip-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  margin: 0 0 var(--s6);
}

.chip-line .queue-badge {
  display: inline-block;
  padding: .15rem var(--s2);
  border: 1px solid var(--ink-line);
  border-radius: 2px;
  background: transparent;
  color: var(--ink-soft);
  font-size: var(--t-caption);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.chip-gloss {
  flex: 1 1 18rem;
  min-width: 0;
  color: var(--ink-soft);
  font-size: var(--t-small);
}

/* ── the progress stepper ───────────────────────────────────────────────────── */

.stepper {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
  counter-reset: step;
}

.step {
  position: relative;
  display: grid;
  grid-template-columns: 1.6rem 1fr;
  column-gap: var(--s3);
  align-items: start;
  padding: 0 0 var(--s4);
}

.step:last-child { padding-bottom: 0; }

/* The rail. Vertical on mobile: a hairline running from one marker to the next. */
.step:not(:last-child)::before {
  content: "";
  position: absolute;
  left: .775rem;
  top: 1.6rem;
  bottom: 0;
  width: 1px;
  background: var(--rule);
}

.step.is-done:not(:last-child)::before { background: var(--teal); }

.step-mark {
  grid-row: 1 / span 2;
  width: 1.6rem;
  height: 1.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--ink-line);
  border-radius: 2px;
  background: var(--surface);
  color: var(--ink-soft);
  font-size: var(--t-caption);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.step-label {
  font-size: var(--t-small);
  line-height: 1.35;
  color: var(--ink-soft);
}

.step-state {
  font-size: var(--t-caption);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  opacity: .8;
}

.step.is-done .step-mark {
  border-color: var(--teal);
  background: var(--teal);
  color: var(--surface);
}

.step.is-done .step-label { color: var(--ink); }

.step.is-current .step-mark {
  border-color: var(--orange);
  background: var(--orange);
  color: var(--surface);
  animation: step-pulse 2.4s ease-in-out infinite;
}

.step.is-current .step-label { color: var(--ink); font-weight: 600; }
.step.is-current .step-state { color: var(--orange); opacity: 1; }

.step.is-held .step-mark {
  border-color: var(--orange);
  background: var(--orange-wash);
  color: var(--orange);
  animation: none;
}

.step.is-held .step-label { color: var(--ink); font-weight: 600; }
.step.is-held .step-state { color: var(--orange); opacity: 1; }

@keyframes step-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--orange-wash); }
  50% { box-shadow: 0 0 0 4px var(--orange-wash); }
}

/* Horizontal from the point the seven labels stop colliding. Seven French stage names do not
   fit the reading column, so on a wide enough screen the panel is allowed to bleed past it —
   the stepper is a figure, not prose, and it is the one thing on this page a supervisor reads
   from across a room. */
@media (min-width: 62rem) {
  .stepper {
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
  }

  .step {
    grid-template-columns: 1fr;
    padding: 0 var(--s3) 0 0;
  }

  .step:not(:last-child)::before {
    top: .775rem;
    bottom: auto;
    left: 1.85rem;
    right: 0;
    width: auto;
    height: 1px;
  }

  .step-mark { grid-row: auto; margin-bottom: var(--s3); }

  /* A fixed label box, so the seven state words sit on one baseline whatever the label wraps
     to. Without it the row reads as seven unrelated captions. */
  .step-label {
    min-height: 4.6rem;
    font-size: var(--t-caption);
    line-height: 1.35;
  }
}

@media (min-width: 62rem) {
  main:not(.wide) section.stages {
    margin-left: calc(-1 * var(--s12));
    margin-right: calc(-1 * var(--s12));
  }
}

/* ── fact tables ────────────────────────────────────────────────────────────── */

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

table.facts { margin: 0 0 var(--s6); }

table.facts th {
  text-align: left;
  width: 14rem;
  padding: var(--s2) var(--s4) var(--s2) 0;
  vertical-align: top;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: var(--t-caption);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}

table.facts td {
  padding: var(--s2) 0;
  vertical-align: top;
  border-top: 1px solid var(--rule);
  font-size: var(--t-small);
}

table.facts tr:first-child th, table.facts tr:first-child td { border-top: 0; }

@media (max-width: 33rem) {
  table.facts, table.facts tbody, table.facts tr, table.facts th, table.facts td {
    display: block;
    width: auto;
  }
  table.facts td { border-top: 0; padding-top: 0; padding-bottom: var(--s3); }
}

/* ── forms ──────────────────────────────────────────────────────────────────── */

form { margin: var(--s6) 0; }

label {
  display: block;
  margin: var(--s6) 0 var(--s2);
  color: var(--ink);
  font-size: var(--t-small);
  font-weight: 600;
}

label .hint { display: block; font-weight: 400; color: var(--ink-soft); }

input[type="text"], input[type="email"], input[type="password"] {
  width: 100%;
  max-width: 30rem;
  min-height: 44px;
  padding: var(--s2) var(--s3);
  border: 1px solid var(--ink-line);
  border-radius: 2px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--t-body);
}

input::placeholder { color: var(--ink-soft); }

/* The file field: the native input is kept — it is what carries `required`, `accept` and the
   browser's own drop target — and simply laid transparently over its own label. No JS
   drag-and-drop, no custom picker, no lost accessibility. */
.file-field {
  position: relative;
  max-width: 30rem;
  margin: 0 0 var(--s2);
}

.file-field input[type="file"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.file-drop {
  display: block;
  margin: 0;
  padding: var(--s4);
  border: 1px dashed var(--ink-line);
  border-radius: 2px;
  background: var(--surface);
  color: var(--ink-soft);
  font-weight: 400;
  text-align: center;
  transition: border-color var(--speed) linear, background var(--speed) linear;
}

.file-field input[type="file"]:hover + .file-drop { border-color: var(--teal); }

.file-field input[type="file"]:focus-visible + .file-drop {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.file-drop b {
  display: block;
  color: var(--ink);
  font-size: var(--t-small);
  font-weight: 600;
}

.file-drop span { display: block; font-size: var(--t-caption); }

.file-names {
  margin: 0;
  padding: 0;
  min-height: 1.2rem;
  color: var(--teal);
  font-family: var(--mono);
  font-size: var(--t-caption);
  overflow-wrap: anywhere;
}

/* Block, not inline. An `<input>` is inline-level and capped at 30rem inside the reading
   column, so an inline button lands in the leftover space BESIDE the last field instead of
   under it. Only the queue table's action buttons stay inline; several share one cell. */
button {
  display: block;
  min-height: 44px;
  margin-top: var(--s6);
  padding: var(--s2) var(--s6);
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: var(--ink);
  color: var(--surface);
  font: inherit;
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: .02em;
  cursor: pointer;
  transition: background var(--speed) linear, border-color var(--speed) linear;
}

button:hover { background: var(--teal); border-color: var(--teal); }
button:disabled { background: var(--ink-soft); border-color: var(--ink-soft); cursor: default; }

:root[data-theme="dark"] button, :root[data-theme="dark"] button:hover { color: #10181E; }

@media (prefers-color-scheme: dark) {
  button, button:hover { color: #10181E; }
  :root[data-theme="light"] button, :root[data-theme="light"] button:hover { color: var(--surface); }
  /* The two rules above set the label of a FILLED button, whose background is dark. The theme
     toggle is a transparent outlined control in the masthead, so `--surface` paints its label the
     colour of the page behind it: on a dark-mode OS switched to light, it was white on white and
     the only control in the header vanished. It follows the ink, always, and is restated at a
     specificity that beats both. */
  .theme-toggle, .theme-toggle:hover,
  :root[data-theme="light"] .theme-toggle, :root[data-theme="light"] .theme-toggle:hover,
  :root[data-theme="dark"] .theme-toggle, :root[data-theme="dark"] .theme-toggle:hover {
    color: var(--ink);
  }
}

:root[data-theme="dark"] .theme-toggle, :root[data-theme="dark"] .theme-toggle:hover,
:root[data-theme="light"] .theme-toggle, :root[data-theme="light"] .theme-toggle:hover {
  color: var(--ink);
}

/* ── the artifact explorer ──────────────────────────────────────────────────── */

p.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2);
  font-size: var(--t-small);
  color: var(--ink-soft);
  margin: 0 0 var(--s4);
  max-width: none;
}

p.crumbs .sep { color: var(--ink-line); }
p.crumbs b { color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }

/* One column on a phone — the tree above, the file below, which is the order they are used in.
   Two from 60rem, where a 15rem navigation column still leaves a full reading measure beside it. */
.explorer {
  display: grid;
  gap: var(--s6);
  margin: 0 0 var(--s6);
}

@media (min-width: 60rem) {
  .explorer {
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: var(--s8);
    align-items: start;
  }

  /* The tree follows the reader down a long file rather than scrolling away from them. */
  .tree {
    position: sticky;
    top: var(--s4);
    max-height: calc(100vh - var(--s8));
    overflow: auto;
  }
}

.tree {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink);
  background: var(--surface);
  padding: var(--s3) var(--s4);
}

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

ul.listing li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule);
  font-size: var(--t-small);
  line-height: 1.4;
}

ul.listing li:first-child { border-top: 0; }
ul.listing li a { overflow-wrap: anywhere; }

/* A directory is bold and carries the separator; a file is not. The two are told apart by weight
   and by the mark, never by colour alone. */
ul.listing li.dir a { font-weight: 600; }
ul.listing li.dir a::after { content: " /"; color: var(--ink-soft); }
ul.listing li.up a { color: var(--ink-soft); font-size: var(--t-caption); letter-spacing: .04em; }
ul.listing li.up a::before { content: "↑ "; }

ul.listing li.is-active {
  margin: 0 calc(-1 * var(--s3));
  padding-left: var(--s3);
  padding-right: var(--s3);
  background: var(--teal-wash);
}

ul.listing li.is-active a { color: var(--ink); font-weight: 600; }

ul.listing .size {
  color: var(--ink-soft);
  font-family: var(--mono);
  font-size: var(--t-caption);
  white-space: nowrap;
}

.pane { min-width: 0; }

.pane-empty {
  border: 1px dashed var(--rule);
  background: var(--surface);
  padding: var(--s8);
  color: var(--ink-soft);
  font-size: var(--t-small);
  max-width: none;
}

/* ── one artifact, rendered ─────────────────────────────────────────────────── */

.view {
  border: 1px solid var(--rule);
  border-top: 2px solid var(--ink);
  background: var(--surface);
  padding: var(--s4) var(--s6) var(--s6);
}

.view-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  padding-bottom: var(--s3);
  margin-bottom: var(--s4);
  border-bottom: 1px solid var(--rule);
}

.view-head h2 {
  margin: 0;
  font-family: var(--mono);
  font-size: var(--t-body);
  font-weight: 600;
  overflow-wrap: anywhere;
}

.view-meta {
  display: flex;
  align-items: baseline;
  gap: var(--s2);
  margin: 0;
  font-size: var(--t-caption);
  color: var(--ink-soft);
}

.view-meta .size { font-family: var(--mono); }
.view-meta .sep { color: var(--ink-line); }

.view-note {
  border-left: 3px solid var(--orange);
  background: var(--orange-wash);
  color: var(--ink);
  padding: var(--s2) var(--s4);
  margin: 0 0 var(--s4);
  font-size: var(--t-small);
  max-width: none;
}

.view-body { overflow-wrap: break-word; }

/* Anything wide — a table, a code block — scrolls inside its own frame. The PAGE never scrolls
   sideways, whatever a generated record contains. */
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--rule);
  margin: 0 0 var(--s4);
}

/* ── generated Markdown ─────────────────────────────────────────────────────── */

/* The document's own `#` heading renders as h2: the page frame owns the h1. The ramp below is
   what keeps five levels legible inside a panel that is itself under an h1. */
.md h2, .md h3, .md h4, .md h5, .md h6 {
  font-family: var(--serif);
  line-height: 1.25;
  font-weight: 600;
  color: var(--ink);
  margin: var(--s8) 0 var(--s3);
}

.md > :first-child { margin-top: 0; }

.md h2 { font-size: var(--t-h2); padding-bottom: var(--s2); border-bottom: 1px solid var(--rule); }
.md h3 { font-size: 1.15rem; }
.md h4 { font-size: 1rem; }
.md h5, .md h6 { font-size: var(--t-small); letter-spacing: .02em; text-transform: uppercase; }

.md p { margin: 0 0 var(--s4); max-width: 72ch; }

.md ul, .md ol { margin: 0 0 var(--s4); padding-left: var(--s6); max-width: 72ch; }
.md li { margin-bottom: var(--s1); }
.md li > ul, .md li > ol { margin: var(--s1) 0 0; }

.md blockquote {
  margin: 0 0 var(--s4);
  padding: var(--s1) var(--s4);
  border-left: 3px solid var(--teal);
  background: var(--teal-wash);
}

.md blockquote p:last-child { margin-bottom: 0; }

.md hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: var(--s6) 0;
}

.md code, .md-table code {
  font-family: var(--mono);
  font-size: .875em;
  padding: .1em .3em;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--ink-wash);
  overflow-wrap: anywhere;
}

.md a { overflow-wrap: anywhere; }

/* ── data tables: Markdown tables and CSV files ─────────────────────────────── */

table.md-table, table.csv-table {
  width: auto;
  min-width: 100%;
  font-size: var(--t-small);
  background: var(--surface);
}

table.md-table th, table.md-table td,
table.csv-table th, table.csv-table td {
  padding: var(--s2) var(--s3);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--rule);
}

table.md-table th, table.csv-table th {
  position: sticky;
  top: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--ink);
  color: var(--ink-soft);
  font-size: var(--t-caption);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}

table.md-table tr:last-child td, table.csv-table tr:last-child td { border-bottom: 0; }

table.md-table .md-c { text-align: center; }
table.md-table .md-r { text-align: right; font-variant-numeric: tabular-nums; }

/* A CSV is a numeric record: monospace and tabular figures are what make a column comparable
   down its length. The header stays in the UI face, since it is a label and not a number. */
table.csv-table td {
  font-family: var(--mono);
  font-size: var(--t-caption);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── code ───────────────────────────────────────────────────────────────────── */

/* The token colours are inlined per page from Pygments (see `render.highlight_css`); everything
   structural — the frame, the gutter, the metrics — is here, in the design tokens. */
/* `--paper`, not `--surface`: the panel around it is already `--surface`, and a code block that
   shared its background would have only a hairline to say where the code starts. */
.hl, pre.plain {
  overflow-x: auto;
  border: 1px solid var(--rule);
  background: var(--paper);
  margin: 0 0 var(--s4);
}

.hl pre, pre.plain {
  margin: 0;
  padding: 0;
  font-family: var(--mono);
  font-size: var(--t-caption);
  line-height: 1.55;
  tab-size: 4;
}

pre.plain { padding: var(--s3) var(--s4); }
.md .hl, .md pre.plain { max-width: none; }

.hl table.hltable {
  width: auto;
  min-width: 100%;
  border-collapse: collapse;
}

/* Every rule below carries `table.hltable` so it outweighs this one — a bare `.hl td.linenos`
   loses to it on specificity and the gutter ends up welded to the code. */
.hl table.hltable td { padding: var(--s3) 0; border: 0; vertical-align: top; }

/* The gutter is not selectable and not copied: a supervisor who copies a snippet out of a review
   should get the code, not the code with a column of numbers welded to its left. */
.hl table.hltable td.linenos {
  width: 1%;
  padding: var(--s3) var(--s3) var(--s3) var(--s4);
  border-right: 1px solid var(--rule);
  background: var(--ink-wash);
  color: var(--ink-soft);
  text-align: right;
  white-space: nowrap;
  user-select: none;
  -webkit-user-select: none;
}

.hl table.hltable td.linenos pre span { color: var(--ink-soft); }

.hl table.hltable td.code {
  width: 100%;
  padding: var(--s3) var(--s4);
}
.hl .hll { display: block; }

/* Pygments emits `<code>` inside `<pre>` (`wrapcode`), which the Markdown rule above would
   otherwise box and tint like an inline span. */
.md .hl code, .hl code, pre.plain code {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  font-size: inherit;
}

/* ── the administrator's queue ──────────────────────────────────────────────── */

/* The wrapper is what guarantees the PAGE never scrolls sideways, whatever a submitter typed
   into the title field. On a tall queue it also becomes the scrollport the sticky header sticks
   to — a header that stuck to the viewport instead would need the wrapper gone, and then a long
   title would push the approve button off-screen. */
div.scroll {
  overflow: auto;
  max-height: 78vh;
  border: 1px solid var(--rule);
  background: var(--surface);
}

table.queue {
  min-width: 58rem;
  font-size: var(--t-caption);
  line-height: 1.45;
}

table.queue th, table.queue td {
  padding: var(--s2) var(--s3);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--rule);
}

table.queue th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  border-bottom: 1px solid var(--ink);
  color: var(--ink-soft);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  white-space: nowrap;
}

table.queue tr:last-child td { border-bottom: 0; }
table.queue td.id { font-family: var(--mono); white-space: nowrap; color: var(--ink-soft); }
/* `break-word`, not `anywhere`: `anywhere` lets the column shrink to a single character, and a
   submitter's title then renders as "Osman metastrat egy". This breaks a word only when the
   word alone does not fit. */
table.queue td.title { font-weight: 600; overflow-wrap: break-word; }
table.queue td.email { color: var(--ink-soft); overflow-wrap: break-word; }
table.queue td.stage { color: var(--ink-soft); font-family: var(--mono); }
table.queue td.num { text-align: right; font-variant-numeric: tabular-nums; }
table.queue td.when { color: var(--ink-soft); }
table.queue td.link { white-space: nowrap; }

/* The detail column needs a floor AND a ceiling: `table-layout: auto` hands the widest column
   whatever is left over, and 160 characters wrapped into 158 px is eight lines — but left
   ungoverned the same column is what pushes the actions off the right edge at 1280. The whole
   text stays on the cell's `title`. */
table.queue td.detail {
  width: 13rem;
  min-width: 11rem;
  color: var(--ink-soft);
}

/* Stacked rather than in a row: two buttons side by side are what makes the actions column
   wide enough to overflow the table at 1280, and a column of them is easier to hit anyway. */
/* In the queue the chip may wrap: `en attente d’une source` on one line is a 230 px column, and
   the ten columns then no longer fit 1280 px. It is still a padded box, so it still reads as a
   chip on two lines. */
table.queue .chip { white-space: normal; }

table.queue td.actions form { display: block; }

table.queue td.actions button {
  display: block;
  width: 100%;
  text-align: left;
  white-space: normal;
}
table.queue form { display: inline; margin: 0; }

table.queue button {
  display: inline-block;
  min-height: 0;
  margin: 0 var(--s1) var(--s1) 0;
  padding: var(--s1) var(--s2);
  border-color: var(--ink-line);
  background: transparent;
  color: var(--ink);
  font-size: var(--t-caption);
  font-weight: 600;
  white-space: nowrap;
}

table.queue button:hover { border-color: var(--ink); background: var(--ink-wash); color: var(--ink); }

table.queue button.act-approve {
  border-color: var(--teal);
  background: var(--teal);
  color: var(--surface);
}

table.queue button.act-approve:hover { background: var(--ink); border-color: var(--ink); }
table.queue button.act-cancel { color: var(--red); border-color: var(--red); }
table.queue button.act-cancel:hover { background: var(--red-wash); border-color: var(--red); color: var(--red); }

:root[data-theme="dark"] table.queue button { color: var(--ink); }
:root[data-theme="dark"] table.queue button.act-approve { color: #10181E; }
:root[data-theme="dark"] table.queue button.act-cancel { color: var(--red); }

@media (prefers-color-scheme: dark) {
  table.queue button { color: var(--ink); }
  table.queue button.act-approve { color: #10181E; }
  table.queue button.act-cancel { color: var(--red); }
}

.table-hint {
  margin: var(--s2) 0 0;
  color: var(--ink-soft);
  font-size: var(--t-caption);
  letter-spacing: .02em;
}

@media (min-width: 80rem) { .table-hint { display: none; } }

.queue-empty {
  border: 1px dashed var(--rule);
  background: var(--surface);
  padding: var(--s8);
  text-align: center;
  color: var(--ink-soft);
}

/* ── the small centred pages: sign-in, not-found, unavailable ───────────────── */

/* The sign-in and refusal pages are one column all the way up: the header rule, the field and
   the footer line share a single left edge, so the page reads as a card rather than as a wide
   frame with something small dropped into the middle of it. */
body.is-slim .masthead-inner, body.is-slim .pagefoot p { max-width: 30rem; }

main.slim { max-width: 30rem; }

main.slim h1 { font-size: 1.5rem; }

/* ── reduced motion ─────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  .step.is-current .step-mark {
    animation: none;
    box-shadow: 0 0 0 3px var(--orange-wash);
  }
}
