/* The question bank.
 *
 * A tool for a licensing body, looked at for hours by people doing careful
 * work. What it has to get right: a table reads cleanly, a stage is legible at
 * a glance, the primary action on a screen is obvious, and nothing draws
 * attention it has not earned.
 *
 * Deliberately plain. No animation, no gradients, one shadow, one accent
 * colour, one violet for the authority stage. Everything else is neutral, and
 * the neutrals do most of the work — a professional interface is mostly the
 * absence of decisions that call attention to themselves.
 *
 * DIRECTION-NEUTRAL THROUGHOUT. There is no `left` or `right` in this file and
 * there must never be one: the interface is Arabic and therefore right-to-left,
 * and a physical margin would mean "the wrong side" on every screen. Use
 * margin-inline-start / padding-inline / inset-inline / text-align: start.
 * `tests/test_design.py` fails on a physical direction.
 *
 * SPACING IS A SCALE, NOT A GUESS. Every gap below is one of --s1..--s7.
 * Inconsistent gaps are where most of a cheap look comes from.
 */

/* IBM Plex Sans Arabic, self-hosted. Arabic and Latin are drawn as one family,
 * which matters on every screen here: question numbers, versions and dates sit
 * inline with Arabic text, and an unmatched pairing is where "something looks
 * off" comes from. SIL Open Font License 1.1 — see static/fonts/README.md.
 *
 * Two subsets per weight, split by unicode-range: a browser rendering an
 * Arabic-only page never downloads the Latin file and vice versa.
 */
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-400-arabic.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1,
    U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF,
    U+FE70-FE74, U+FE76-FEFC;
}

@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2122, U+2212, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-600-arabic.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1,
    U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF,
    U+FE70-FE74, U+FE76-FEFC;
}

@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+2122, U+2212, U+FEFF, U+FFFD;
}

:root {
  /* FONT: the single line to change if the client has an institutional
   * typeface. Whatever replaces it must have real Arabic coverage — a
   * Latin-first stack falling back for Arabic mismatches baseline and weight
   * mid-sentence, which is immediately visible. */
  --font-body: "IBM Plex Sans Arabic", system-ui, sans-serif;

  /* Ink, in three weights. Not pure black: #000 on white is harsher than it
   * needs to be at the line-height Arabic wants. `--ink-quiet` is for labels
   * and metadata, `--ink-faint` for the things that are present but not being
   * read — placeholder dashes, disabled text. */
  --ink: #16191d;
  --ink-quiet: #59636f;
  --ink-faint: #8b95a1;
  --on-accent: #ffffff;

  /* Surfaces, lightest to deepest. The page is white, the app sits on a tint
   * so that white panels read as raised without needing a shadow. */
  --page: #ffffff;
  /* Deepened deliberately. The old canvas was two per cent off the page, so
   * a white panel on it read as a rectangle of the same colour with a border
   * — the eye separated the regions by the line rather than by the surface,
   * which is what "borders everywhere" looks like. */
  --canvas: #eef1f5;
  --raised: #f6f8fa;
  --raised-deep: #e6ebf0;

  /* Two rules. `line` separates rows inside a thing; `line-strong` closes the
   * thing itself. Using one weight for both is what makes a table look like a
   * spreadsheet. */
  --line: #e3e8ee;
  --line-strong: #cbd3dc;

  /* One accent, for the primary action and for nothing decorative. */
  --accent: #1b4571;
  --accent-hover: #133357;
  --accent-quiet: #eaf1f8;
  --accent-ring: rgb(27 69 113 / 18%);

  /* Status tints. A badge carries its meaning in text as well: colour alone is
   * never a label. */
  --neutral: #545f6b;
  --neutral-bg: #eef1f4;
  --info: #1b4f8a;
  --info-bg: #e8f0f9;
  --work: #8a5a00;
  --work-bg: #fbf2df;
  --ok: #1c6b39;
  --ok-bg: #e7f4eb;
  --danger: #a4161a;
  --danger-bg: #fdf0f0;

  /* Stage identity. The first stage borrows the accent's own family; the
   * second gets a violet that nothing else in the interface uses, so "the
   * second review has it" is never confusable with a status, a warning or a
   * link. */
  --authority: #6b21a8;
  --authority-bg: #f4ecfb;

  /* ROLE IDENTITY — one hue each, for the band across the masthead.
   *
   * Somebody with two accounts open, or returning to a machine a colleague
   * was using, should know whose account they are in before reading
   * anything. Four roles, four hues, and the pair most worth telling apart is
   * the two management ones: they see the same screens and only one of them
   * can change anything.
   *
   * **Never colour alone.** The role's name sits under the band, always. A
   * band with no name would fail for the one reader in twelve who cannot
   * separate two of these, and in a photocopy or a screenshot in a report.
   *
   * Chosen dark enough to read as deliberate against white and distinct in
   * hue rather than only in lightness. */
  --role-project-admin: #1b4571;
  --role-project-reviewer: #0f6f5c;
  --role-authority-reviewer: #6b21a8;
  --role-authority-admin: #8a5a00;
  --role-unknown: #59636f;

  /* The spacing scale. Nothing is spaced by eye. */
  --s1: 0.25rem;
  --s2: 0.5rem;
  --s3: 0.75rem;
  --s4: 1rem;
  --s5: 1.5rem;
  --s6: 2rem;
  --s7: 3rem;

  --radius: 6px;
  --radius-lg: 12px;

  /* One height for everything you can click or type into. Controls of three
   * different heights side by side is most of what makes an interface read as
   * assembled rather than designed. */
  --control: 2.5rem;

  /* Two elevations, both restrained. `--lift` is for a surface resting on the
   * canvas — a panel, the masthead. `--lift-raised` is for something that has
   * come forward over the page: a menu, the action bar. Anything needing more
   * than these two is decoration. */
  --lift: 0 1px 2px rgb(16 24 40 / 5%), 0 2px 6px rgb(16 24 40 / 6%);
  --lift-raised: 0 2px 4px rgb(16 24 40 / 6%), 0 12px 28px rgb(16 24 40 / 10%);

  /* Two widths. Prose is capped at a readable measure; tables get the room
   * they need, and the master table needs seven columns of it. */
  --measure: 46rem;
  --wide: 88rem;
}

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

body {
  margin: 0;
  font-family: var(--font-body);
  /* Arabic needs more leading than Latin at the same size. */
  font-size: 1.0625rem;
  line-height: 1.8;
  color: var(--ink);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
}

.page {
  max-inline-size: var(--wide);
  margin-inline: auto;
  padding-inline: var(--s5);
  padding-block: var(--s5) var(--s7);
}

/* Prose stays readable on a wide page. Tables, panels and figures opt out. */
p {
  max-inline-size: var(--measure);
}

/* ---------------------------------------------------------------------------
 * Type scale
 *
 * Four levels and real distance between them. Everything at one size is the
 * single biggest reason an interface reads as unconsidered.
 * ------------------------------------------------------------------------ */

h1 {
  font-size: 1.85rem;
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin-block: 0 var(--s2);
}

h2 {
  font-size: 1.2rem;
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: -0.005em;
  margin-block: var(--s6) var(--s3);
}

/* A section label rather than a heading: small, spaced and quiet, so it reads
 * as the name of what follows instead of competing with it. This is the level
 * that was doing nothing before — it sat a hair under body text and looked
 * like emphasis. */
h3 {
  font-size: 0.8rem;
  line-height: 1.5;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-quiet);
  margin-block: var(--s5) var(--s2);
}

h1 + p,
h2 + p,
h3 + p {
  margin-block-start: 0;
}

/* The sentence under a page title: what this screen is, or how much is on it. */
.lede {
  color: var(--ink-quiet);
  margin-block: 0;
}

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

/* ---------------------------------------------------------------------------
 * Masthead
 * ------------------------------------------------------------------------ */

.masthead {
  position: relative;
  display: flex;
  gap: var(--s5);
  align-items: center;
  flex-wrap: wrap;
  background: var(--page);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--lift);
  padding: var(--s4) var(--s5);
  margin-block-end: var(--s5);
  overflow: hidden;
}

/* The role band. Drawn as a pseudo-element across the block-start edge, so it
 * needs no extra markup and cannot be mistaken for a control.
 *
 * `inset-inline` rather than left/right, so it spans the header in either
 * writing direction. */
.masthead::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 4px;
  background: var(--role, var(--role-unknown));
}

.masthead.role-project_admin {
  --role: var(--role-project-admin);
}

.masthead.role-project_reviewer {
  --role: var(--role-project-reviewer);
}

.masthead.role-authority_reviewer {
  --role: var(--role-authority-reviewer);
}

.masthead.role-authority_admin {
  --role: var(--role-authority-admin);
}

/* Who is signed in: the name, and under it the role in that role's own
 * colour. **The colour never carries the meaning by itself** — the name of
 * the role is always there, so the band is a second signal rather than the
 * only one. */
.whoami {
  margin-inline-start: auto;
  display: flex;
  flex-direction: column;
  line-height: 1.35;
  text-align: end;
}

.whoami-name {
  font-weight: 600;
  font-size: 0.95rem;
}

.whoami-role {
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--role, var(--role-unknown));
}

/* A link home, and home differs by role. Styled as the label it replaced
 * rather than as a link, so it does not read as one more nav entry competing
 * with the queue. */
.masthead .wordmark {
  font-weight: 600;
  font-size: 1.05rem;
  text-decoration: none;
  color: inherit;
  padding-inline-end: var(--s5);
  border-inline-end: 1px solid var(--line);
}

.masthead nav {
  display: flex;
  gap: var(--s4);
  flex-wrap: wrap;
}

.masthead nav a {
  color: var(--ink-quiet);
  text-decoration: none;
  font-size: 0.97rem;
  padding: var(--s1) var(--s3);
  border-radius: var(--radius);
}

.masthead nav a:hover {
  color: var(--ink);
  background: var(--raised-deep);
}

.masthead .spacer {
  margin-inline-start: auto;
  font-size: 0.9rem;
  color: var(--ink-quiet);
}

/* Sign out is present, not offered. It is the one control on the masthead
 * and it should not compete with the navigation beside it. */
.quiet-button {
  padding-block: var(--s2) !important;
  padding-inline: var(--s3) !important;
  min-block-size: auto !important;
  font-size: 0.88rem !important;
  font-weight: 500 !important;
  color: var(--ink-quiet) !important;
  border-color: var(--line) !important;
}

.quiet-button:hover {
  color: var(--ink) !important;
  border-color: var(--line-strong) !important;
}

/* Changing your own password sits beside sign out, and reads as quietly as the
 * navigation does. Not a button: it opens a screen, and the one control on the
 * masthead is still sign out. */
.account-link {
  color: var(--ink-quiet);
  text-decoration: none;
  font-size: 0.88rem;
  padding-block: var(--s1);
  padding-inline: var(--s3);
  border-radius: var(--radius);
  white-space: nowrap;
}

.account-link:hover {
  color: var(--ink);
  background: var(--raised-deep);
}

/* ---------------------------------------------------------------------------
 * Page furniture
 * ------------------------------------------------------------------------ */

main {
  background: var(--page);
  border: 1px solid var(--line);
  box-shadow: var(--lift);
  border-radius: var(--radius-lg);
  box-shadow: var(--lift);
  padding: var(--s6);
}

/* Title on one side, the screen's single primary action on the other, with a
 * rule under it so the head reads as a head. */
.page-head {
  display: flex;
  gap: var(--s4);
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  padding-block-end: var(--s4);
  margin-block-end: var(--s5);
  border-block-end: 1px solid var(--line);
}

/* A page whose title is a bare h1 still wants the same separation. */
main > h1:first-child {
  padding-block-end: var(--s4);
  margin-block-end: var(--s5);
  border-block-end: 1px solid var(--line);
}

/* ---------------------------------------------------------------------------
 * Tables — most of this application is a table
 *
 * Room to breathe, one hairline between rows, a header that reads as a header
 * without shouting, and no vertical rules. Grid lines in both directions is
 * what makes a table look like a spreadsheet somebody exported.
 * ------------------------------------------------------------------------ */

/* A table whose rows are dragged over must not also sweep its own text into
 * a browser selection: the pointer is being used for something else. The
 * checkboxes and links stay selectable and focusable — this suppresses the
 * highlight, not the interaction. */
table[data-selectable] tbody {
  user-select: none;
  -webkit-user-select: none;
}

table {
  inline-size: 100%;
  border-collapse: collapse;
  margin-block: var(--s4) var(--s5);
  font-size: 0.97rem;
  background: var(--page);
}

thead th {
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-quiet);
  white-space: nowrap;
  background: var(--raised);
  border-block-end: 1px solid var(--line-strong);
  padding-block: var(--s3);
}

/* The header stays while a five-hundred-row table scrolls. Without it the
 * column names are gone by row twenty and every cell after that is a guess. */
thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
}

/* Start, not the physical edge: this is the reading edge in both directions. */
th,
td,
caption {
  text-align: start;
  /* Rows people read for an hour. The extra quarter-rem is the difference
   * between a table and a spreadsheet. */
  padding: var(--s3) var(--s4);
  vertical-align: middle;
}

tbody td {
  padding-block: var(--s4);
}

td {
  border-block-end: 1px solid var(--line);
}

/* Zebra, very faint. Enough to follow a row across seven columns, not enough
 * to be a pattern. */
tbody tr:nth-child(even) {
  background: color-mix(in srgb, var(--raised) 55%, transparent);
}

/* One hover, and a marker on the reading edge so the row being pointed at is
 * unambiguous even where the tint is subtle. `box-shadow` rather than a
 * border, so nothing shifts by three pixels as the pointer moves. */
tbody tr {
  transition: background-color 90ms ease;
}

tbody tr:hover {
  background: var(--accent-quiet);
  box-shadow: inset 3px 0 0 0 var(--accent);
}

/* In a right-to-left page the inset shadow above lands on the physical left,
 * which is the row's *end*. Flipped here so it sits on the reading edge in
 * both directions — there is no logical equivalent for a shadow offset. */
[dir="rtl"] tbody tr:hover {
  box-shadow: inset -3px 0 0 0 var(--accent);
}

/* A row whose box is ticked stays visibly chosen after the pointer leaves —
 * during a drag over fifty rows, that is the only feedback there is. */
tbody tr:has(input[type="checkbox"]:checked) {
  background: var(--accent-quiet);
}

tbody tr:last-child td {
  border-block-end: none;
}

/* The whole table gets one enclosing rule, drawn on the wrapper rather than
 * per cell. */
table {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

caption {
  caption-side: block-start;
  font-weight: 600;
  padding-inline: 0;
}

td a {
  color: var(--accent);
  text-decoration-color: color-mix(in srgb, var(--accent) 35%, transparent);
  text-underline-offset: 0.2em;
}

td a:hover {
  text-decoration-color: currentColor;
}

/* Numbers line up under each other and read from the same edge whichever way
 * the page runs, so a column of versions or counts can be scanned. */
/* Figures line up in a column and are read from the end, the way a column of
 * numbers is read in any direction. */
.numeric {
  font-variant-numeric: tabular-nums;
  text-align: end;
  font-feature-settings: "tnum";
}

th.numeric {
  text-align: end;
}

/* A code, a version, a fingerprint. Tabular so digits line up in a column. */
.code {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.row-actions {
  display: flex;
  gap: var(--s4);
  flex-wrap: wrap;
}

.pagination {
  display: flex;
  gap: var(--s4);
  align-items: center;
  color: var(--ink-quiet);
  font-size: 0.95rem;
}

/* The select column: as narrow as a checkbox, and never the thing the eye
 * lands on first. */
.master .pick {
  inline-size: 1%;
  white-space: nowrap;
}

.master .pick input {
  inline-size: auto;
  margin: 0;
}

/* ---------------------------------------------------------------------------
 * Badges — colour and text, never colour alone
 * ------------------------------------------------------------------------ */

.badge {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3em;
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.7;
  padding-inline: var(--s3);
  border-radius: 999px;
  white-space: nowrap;
  color: var(--neutral);
  background: var(--neutral-bg);
  border: 1px solid transparent;
}

.badge.state-pending_review {
  color: var(--info);
  background: var(--info-bg);
  border-color: color-mix(in srgb, var(--info) 22%, transparent);
}

/* The middle of the pipeline, in the working amber the design uses for
 * "somebody is doing this". It was removed when the second review briefly
 * stopped being a state and is back with it. */
.badge.state-awaiting_second_review {
  color: var(--work);
  background: var(--work-bg);
  border-color: color-mix(in srgb, var(--work) 22%, transparent);
}

.badge.state-approved {
  color: var(--ok);
  background: var(--ok-bg);
  border-color: color-mix(in srgb, var(--ok) 22%, transparent);
}

/* ---------------------------------------------------------------------------
 * Review stages — the one distinction most worth not getting wrong
 *
 * The two stages do the same job at different points, and the client's names
 * for them part only at the end. Three signals carry the difference, and each
 * works without the others: a short name, a colour, and a numeral.
 *
 * The numeral is what makes this safe. Roughly one man in twelve cannot
 * separate these two hues reliably, and neither can a photocopy — so the
 * colour is the fast signal and the mark is the certain one.
 * ------------------------------------------------------------------------ */

.badge.stage-project {
  color: var(--info);
  background: var(--info-bg);
  border-color: color-mix(in srgb, var(--info) 28%, transparent);
}

.badge.stage-authority {
  color: var(--authority);
  background: var(--authority-bg);
  border-color: color-mix(in srgb, var(--authority) 28%, transparent);
}

/* The numeral. Set apart from the name so it reads as a marker rather than as
 * part of the word. */
.badge .mark {
  font-variant-numeric: tabular-nums;
  font-size: 0.9em;
  opacity: 0.7;
}

/* The sentence on the review screen saying which stage this is, and — for the
 * authority — that the version on screen is the one the project team approved.
 * That is the actual difference between the two stages, so it is written out
 * rather than left to be inferred from a badge. */
.standing {
  border-inline-start: 3px solid var(--line-strong);
  background: var(--raised);
  border-radius: var(--radius);
  padding: var(--s3) var(--s4);
  margin-block: 0 var(--s5);
  max-inline-size: none;
  font-size: 0.97rem;
  font-weight: 600;
}

.standing.stage-project {
  border-inline-start-color: var(--info);
  background: var(--info-bg);
  color: var(--info);
}

.standing.stage-authority {
  border-inline-start-color: var(--authority);
  background: var(--authority-bg);
  color: var(--authority);
}

/* ---------------------------------------------------------------------------
 * Panels and cards
 * ------------------------------------------------------------------------ */

/* A bounded group of related controls or facts, set off from the page. The
 * distribution controls and the review screen's specification are both one. */
/* A panel sits on the page rather than being drawn on it: a lighter fill and
 * a real shadow, so the eye separates it without needing a heavy border. */
.panel {
  box-shadow: var(--lift);
}

.panel {
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--s5);
}

.cards {
  list-style: none;
  margin-block: var(--s4);
  margin-inline: 0;
  padding: 0;
  display: grid;
  gap: var(--s4);
  grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr));
}

.card {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--page);
  box-shadow: var(--lift);
  padding: var(--s5);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

.card-head {
  display: flex;
  gap: var(--s3);
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
}

.card-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s1) var(--s4);
  margin: 0;
}

.card-facts dt {
  color: var(--ink-quiet);
  font-size: 0.9rem;
}

.card-facts dd {
  margin: 0;
}

.card-note {
  margin: 0;
  padding: var(--s3) var(--s4);
  background: var(--raised);
  border-inline-start: 3px solid var(--line-strong);
  border-radius: var(--radius);
  font-size: 0.95rem;
}

.card .actions {
  margin-block-start: auto;
}

/* ---------------------------------------------------------------------------
 * Forms
 *
 * A label above its field with room between them, generous padding inside, and
 * a focus ring you cannot miss. Cramped inputs with the label jammed against
 * them is most of what "90s website" means.
 * ------------------------------------------------------------------------ */

label {
  display: block;
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--ink-quiet);
  margin-block-end: var(--s2);
}

input[type="text"],
input[type="search"],
input[type="password"],
input[type="date"],
input[type="number"],
input[type="file"],
textarea,
select {
  inline-size: 100%;
  max-inline-size: var(--measure);
  font: inherit;
  color: inherit;
  min-block-size: var(--control);
  padding: var(--s2) var(--s4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--page);
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

/* A textarea is the one control that is not a single line, so it opts out of
 * the shared height. */
textarea {
  min-block-size: 6rem;
  padding-block: var(--s3);
}

textarea {
  line-height: 1.85;
  resize: vertical;
}

input::placeholder,
textarea::placeholder {
  color: var(--ink-faint);
}

input:hover,
textarea:hover,
select:hover {
  border-color: var(--ink-faint);
}

/* One focus treatment for everything focusable: a ring in the accent, offset
 * so it never sits on the border it is announcing. */
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
button:focus-visible,
a:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

input:focus,
textarea:focus,
select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

input[disabled],
select[disabled],
textarea[disabled] {
  background: var(--raised-deep);
  color: var(--ink-faint);
  cursor: not-allowed;
}

.field {
  margin-block-end: var(--s5);
}

.help {
  color: var(--ink-quiet);
  font-size: 0.9rem;
  font-weight: 400;
  line-height: 1.6;
  margin-block: var(--s2) 0;
  max-inline-size: var(--measure);
}

/* ---------------------------------------------------------------------------
 * Tabs — غير مسند · قيد المراجعة · البنك النهائي
 *
 * The strip replaced a six-field filter bar, and it has to read as a place
 * you are standing rather than as three links: the current tab sits on the
 * page, the others sit behind it. One underline carries that, drawn on the
 * block-end edge so it works unchanged in either writing direction.
 *
 * The count is the point of the strip as much as the name is. It is what
 * tells an administrator there is work waiting on a tab they are not
 * looking at, so it is set in the same weight as the label rather than
 * shrunk into a footnote.
 * ------------------------------------------------------------------------ */
.tabs {
  display: flex;
  gap: var(--s5);
  flex-wrap: wrap;
  align-items: stretch;
  border-block-end: 1px solid var(--line);
  margin-block-end: var(--s5);
}

/* The four work queues in one group, البنك النهائي in another, with a rule
 * between them — the client drew it that way, and it says the right thing: the
 * four are places work is happening and the fifth is where it has finished.
 *
 * The separator is a logical inline-start border, so it lands between the last
 * work tab and the bank in either writing direction and needs no second rule
 * if an English interface is ever switched on. (Naming the physical property
 * it replaces would trip this file's own lint, which is the lint working.) */
.tab-group {
  display: flex;
  gap: var(--s5);
  align-items: stretch;
  flex-wrap: wrap;
}

.tab-group + .tab-group {
  padding-inline-start: var(--s5);
  margin-inline-start: var(--s2);
  border-inline-start: 1px solid var(--line-strong);
}

.tab {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding-block: var(--s3);
  color: var(--ink-quiet);
  text-decoration: none;
  font-weight: 500;
  /* Reserves the space the current tab's thicker rule will take, so nothing
   * shifts by two pixels when the selection moves. */
  border-block-end: 3px solid transparent;
  margin-block-end: -1px;
  transition: color 120ms ease, border-color 120ms ease;
}

.tab:hover {
  color: var(--ink);
}

.tab.current {
  color: var(--accent);
  border-block-end-color: var(--accent);
  font-weight: 600;
}

/* The count as a badge rather than a number beside a word: a pill reads as
 * "how many are in here", which is what it is, and it keeps its shape when
 * the figure goes from 5 to 470. */
.tab-count {
  background: var(--raised-deep);
  border-radius: 999px;
  padding-inline: var(--s2);
  min-inline-size: 1.6rem;
  text-align: center;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-quiet);
  font-variant-numeric: tabular-nums;
}

.tab.current .tab-count {
  background: var(--accent-quiet);
  color: var(--accent);
}

/* A short aside inside a cell — who used to hold this, who is revising it.
 * Its own line, because a table cell that wraps mid-phrase is worse than one
 * that is two lines tall. */
.note {
  display: block;
  font-size: 0.85rem;
  color: var(--ink-quiet);
}

/* A filter bar reads as one control, not a stack of unrelated fields. */
.filters {
  display: flex;
  gap: var(--s4);
  flex-wrap: wrap;
  align-items: flex-end;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--s4) var(--s5);
  margin-block-end: var(--s5);
}

.filters .field {
  margin-block-end: 0;
  min-inline-size: 11rem;
  flex: 1 1 11rem;
}

.filters label {
  margin-block-end: var(--s1);
  font-size: 0.85rem;
}

.filters select,
.filters input {
  max-inline-size: none;
  padding-block: var(--s2);
}

.filters .actions {
  margin-block-start: 0;
}

.option {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--s4) var(--s5);
  margin-block-end: var(--s4);
  background: var(--raised);
}

.option legend {
  font-weight: 600;
  padding-inline: var(--s2);
}

.checkbox {
  display: flex;
  gap: var(--s2);
  align-items: center;
}

.checkbox input {
  inline-size: auto;
}

.checkbox label {
  margin-block-end: 0;
}

/* ---------------------------------------------------------------------------
 * Buttons — exactly one filled button per screen
 * ------------------------------------------------------------------------ */

button,
.button {
  font: inherit;
  font-weight: 600;
  font-size: 0.95rem;
  min-block-size: var(--control);
  padding: var(--s2) var(--s5);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--page);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  white-space: nowrap;
  transition: background-color 120ms ease, border-color 120ms ease,
    box-shadow 120ms ease;
  line-height: 1.4;
}

button:hover,
.button:hover {
  background: var(--raised-deep);
  border-color: var(--ink-faint);
}

button.primary,
.button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

button.primary:hover,
.button.primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

/* The quieter of two adjacent buttons. `button` already draws unfilled, so
 * this names the intent rather than adding a treatment — which is the point:
 * only one action on a screen may look primary. */
.secondary {
  background: var(--page);
}

/* For an action that cannot be undone. It is the primary action on its screen
 * so it has to look like one, but the calm accent would make an irreversible
 * step read as routine. */
button.danger,
.button.danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--on-accent);
}

button.danger:hover,
.button.danger:hover {
  background: #7d1013;
  border-color: #7d1013;
}

button[disabled],
button[disabled]:hover {
  opacity: 0.45;
  cursor: not-allowed;
  background: var(--raised);
  border-color: var(--line-strong);
}

.actions {
  display: flex;
  gap: var(--s3);
  align-items: center;
  flex-wrap: wrap;
  margin-block-start: var(--s4);
}

/* ---------------------------------------------------------------------------
 * Callouts, warnings, messages, empty states
 * ------------------------------------------------------------------------ */

.callout {
  border: 1px solid var(--line);
  border-inline-start: 3px solid var(--accent);
  background: var(--accent-quiet);
  border-radius: var(--radius);
  padding: var(--s4) var(--s5);
  margin-block-end: var(--s5);
}

.callout h2 {
  margin-block-start: 0;
  font-size: 1.05rem;
}

.callout > :last-child {
  margin-block-end: 0;
}

/* Stop and read. */
.warning {
  border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
  border-inline-start: 3px solid var(--danger);
  background: var(--danger-bg);
  color: var(--danger);
  padding: var(--s5);
  border-radius: var(--radius);
  margin-block-end: var(--s5);
}

.warning h2 {
  margin-block-start: 0;
}

.warning ul {
  margin-block-end: 0;
  /* Not a physical padding: the marker sits on the start edge either way. */
  padding-inline-start: var(--s5);
}

.errors {
  color: var(--danger);
  margin-block: var(--s2);
  font-weight: 600;
}

.messages {
  list-style: none;
  margin-block: 0 var(--s5);
  margin-inline: 0;
  padding: 0;
  display: grid;
  gap: var(--s2);
  max-inline-size: var(--measure);
}

.messages li {
  background: var(--ok-bg);
  border: 1px solid color-mix(in srgb, var(--ok) 28%, transparent);
  border-inline-start: 3px solid var(--ok);
  border-radius: var(--radius);
  padding: var(--s3) var(--s4);
}

/* An empty state should look like a decision, not like a page that failed to
 * load. Centred, generous, quiet, and never a bare sentence on white. */
/* An empty screen should say what it means, not leave a sentence floating
 * where a table was. The mark is drawn in CSS — a ring with a rule through it
 * — rather than shipped as an asset: it needs no font coverage, no request,
 * and no decision about which icon set this project uses. */
.empty {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
  text-align: center;
  max-inline-size: 28rem;
  margin-inline: auto;
  padding-block: var(--s7);
}

/* The mark: a ring with a rule through it. Drawn in CSS as two boxes rather
 * than shipped as an asset — it needs no request, no font coverage, and no
 * decision about which icon set this project uses. No gradient: the rule is
 * a two-pixel box, not a fill. */
.empty::before {
  content: "";
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border-radius: 50%;
  border: 2px solid var(--line-strong);
}

.empty::after {
  content: "";
  position: absolute;
  inset-block-start: calc(var(--s7) + 1.25rem);
  inline-size: 1.15rem;
  block-size: 2px;
  background: var(--line-strong);
}

.empty-note {
  color: var(--ink-quiet);
  font-size: 0.92rem;
  margin: 0;
}

.empty {
  color: var(--ink-quiet);
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--s7) var(--s5);
  text-align: center;
  max-inline-size: none;
  margin-block: var(--s4);
}

.done {
  color: var(--ok);
  font-weight: 600;
}

/* ---------------------------------------------------------------------------
 * Figures — the reviewer's progress and the admin dashboard
 * ------------------------------------------------------------------------ */

.progress {
  display: grid;
  gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  margin-block: var(--s4) var(--s6);
}

.stat {
  background: var(--page);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--lift);
  padding: var(--s4) var(--s5);
}

.figure {
  display: block;
  font-size: 2rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.stat .label {
  display: block;
  color: var(--ink-quiet);
  font-size: 0.88rem;
  margin-block-start: var(--s1);
}

/* ---------------------------------------------------------------------------
 * The review screen — the heart of the product
 *
 * One page carrying everything about a question, which is the client's first
 * principle. The layout's whole job is to make a long single-column form
 * readable: the specification reads as a fixed panel the reviewer checks
 * against, and the editable content reads as the work.
 * ------------------------------------------------------------------------ */

.review {
  max-inline-size: 62rem;
}

.review-head {
  display: flex;
  gap: var(--s4);
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  padding-block-end: var(--s4);
  border-block-end: 1px solid var(--line);
  margin-block-end: var(--s5);
}

.review-head h1 {
  margin-block-end: var(--s1);
}

.review-head-end {
  display: flex;
  gap: var(--s4);
  align-items: center;
  flex-wrap: wrap;
}

/* The ❓ guide link, present on every review screen and gating nothing. */
.guide-link {
  color: var(--ink-quiet);
  text-decoration: none;
  white-space: nowrap;
  font-size: 0.95rem;
}

.guide-link:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* The token letters — KF, DIR, IND. Small, quiet, and never the main label:
 * the reviewer reads the Arabic and the code is there to be checked against. */
.token {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink-quiet);
  background: var(--raised-deep);
  border-radius: var(--radius);
  padding-inline: var(--s2);
  white-space: nowrap;
}

/* المواصفات — read-only, and it has to look it. A tinted panel with no inputs,
 * visibly a different kind of thing from the form below it. */
.specification {
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--s5);
  margin-block-end: var(--s6);
}

.specification h2 {
  margin-block-start: 0;
  font-size: 0.84rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-quiet);
}

.specification dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: var(--s4) var(--s6);
  margin: 0;
}

.specification dt {
  color: var(--ink-quiet);
  font-size: 0.85rem;
  margin-block-end: var(--s1);
}

.specification dd {
  margin: 0;
  font-weight: 600;
  line-height: 1.6;
}

/* Each part of the question is its own section, separated by space rather than
 * by a rule — the form is long and a line between every field would fence it. */
.review-form section {
  margin-block-end: var(--s6);
}

.review-form section > h2 {
  margin-block-start: 0;
  padding-block-end: var(--s2);
  border-block-end: 1px solid var(--line);
}

.review-form textarea,
.review-form input[type="text"],
.review-form select {
  max-inline-size: none;
}

.options {
  display: grid;
  gap: var(--s4);
}

/* Two buttons, and only one of them filled. */
.review-actions {
  display: flex;
  gap: var(--s3);
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  padding-block-start: var(--s5);
  border-block-start: 1px solid var(--line);
}

/* السابق ／ 1 من 50 ／ التالي */
.pager {
  display: flex;
  gap: var(--s5);
  align-items: center;
  justify-content: center;
  margin-block-start: var(--s6);
  padding-block-start: var(--s5);
  border-block-start: 1px solid var(--line);
}

.pager a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}

.pager a:hover {
  text-decoration: underline;
}

.position {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink-quiet);
}

/* The read-only rendering of the options, on the management screens. */
.options-read {
  list-style: none;
  margin-block: var(--s3);
  margin-inline: 0;
  padding: 0;
  display: grid;
  gap: var(--s2);
}

.options-read li {
  padding: var(--s3) var(--s4);
  border: 1px solid var(--line);
  border-inline-start: 3px solid var(--line-strong);
  background: var(--page);
  border-radius: var(--radius);
}

.correct {
  border-inline-start-color: var(--ok);
  background: var(--ok-bg);
  font-weight: 600;
}

.notes {
  background: var(--work-bg);
  border-inline-start: 3px solid var(--work);
  border-radius: var(--radius);
  padding: var(--s3) var(--s4);
  max-inline-size: none;
}

/* The question preview, on the read-only screens. */
.preview dt {
  font-weight: 600;
  margin-block-start: var(--s3);
  color: var(--ink-quiet);
  font-size: 0.9rem;
}

.preview dd {
  margin-inline-start: 0;
  padding-inline-start: var(--s4);
  border-inline-start: 3px solid var(--line-strong);
}

/* ---------------------------------------------------------------------------
 * The change log
 * ------------------------------------------------------------------------ */

.version {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--s3) var(--s4);
  margin-block-end: var(--s2);
  background: var(--page);
}

.version[open] {
  background: var(--raised);
}

.version summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 0.95rem;
}

.version table {
  margin-block-end: 0;
}

/* القيمة قبل and القيمة بعد, side by side and told apart at a glance. */
.was {
  background: var(--danger-bg);
  text-decoration: line-through;
  text-decoration-color: color-mix(in srgb, var(--danger) 45%, transparent);
}

.now {
  background: var(--ok-bg);
}

.approvals {
  list-style: none;
  margin-block: var(--s3) var(--s5);
  margin-inline: 0;
  padding: 0;
  display: grid;
  gap: var(--s2);
}

.approvals li {
  display: flex;
  gap: var(--s3);
  align-items: center;
  flex-wrap: wrap;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--s2) var(--s4);
  font-size: 0.95rem;
}

/* ---------------------------------------------------------------------------
 * Selecting — the bar above every tab's table
 *
 * A range, two quick pickers, the live count and a clear. One row on a wide
 * screen and a stack on a narrow one, which `flex-wrap` gives without a
 * breakpoint.
 *
 * The count is pushed to the far end with `margin-inline-start: auto` — the
 * logical property, so it lands at the physical left in this right-to-left
 * interface and would move to the right in an English one without a second
 * rule.
 * ------------------------------------------------------------------------ */

.selection {
  display: flex;
  gap: var(--s5);
  align-items: center;
  flex-wrap: wrap;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--s3) var(--s4);
  margin-block-end: var(--s4);
}

.selection .quick {
  display: flex;
  gap: var(--s2);
  align-items: center;
  flex-wrap: wrap;
}

/* One sentence saying how a range is chosen. It is the only instruction on
 * the screen, and it earns its place because shift-click is discoverable only
 * to somebody who already suspects it is there. */
.selection-hint {
  margin: 0;
  font-size: 0.9rem;
  color: var(--ink-quiet);
  max-inline-size: 34rem;
}

.selection label {
  margin-block-end: 0;
  font-size: 0.9rem;
  color: var(--ink-quiet);
  white-space: nowrap;
}

.selection select {
  max-inline-size: 14rem;
  padding-block: var(--s2);
}

.selection .selected {
  margin-block: 0;
  margin-inline-start: auto;
}

/* A button that reads as a link: clearing is an escape hatch, not one of the
 * things the bar is for. */
.link {
  background: none;
  border: none;
  color: var(--accent);
  padding: var(--s1) var(--s2);
  text-decoration: underline;
  cursor: pointer;
}

/* For a label that a screen reader needs and the eye does not, because the
 * control's first option already says the same thing. Not `display: none`,
 * which removes it from the accessibility tree as well. */
.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------------------
 * The action bar — the assignment control
 *
 * Pinned to the foot of the viewport and present only while something is
 * selected. It replaced a multi-select sitting below five hundred rows, which
 * read as a form field that happened to be there rather than as the screen's
 * one action, and which you had to scroll to after making a selection you
 * could no longer see.
 *
 * It is allowed to be the loudest thing on the screen — a raised surface, a
 * real shadow, one filled button — because it appears only when the
 * administrator has already decided to act. Nothing else here earns that.
 * ------------------------------------------------------------------------ */

.action-bar {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 20;
  background: var(--page);
  border-block-start: 1px solid var(--line-strong);
  box-shadow: 0 -1px 3px rgb(16 24 40 / 5%), 0 -8px 24px rgb(16 24 40 / 8%);
  padding-block: var(--s3);
  padding-inline: var(--s5);
}

.action-bar[hidden] {
  display: none;
}

.action-bar-inner {
  max-inline-size: var(--wide);
  margin-inline: auto;
  display: flex;
  gap: var(--s4);
  align-items: center;
  flex-wrap: wrap;
}

/* The count leads, because it is the fact being acted on. Tabular figures so
 * it does not jitter as the number changes during a drag. */
.action-bar-count {
  margin: 0;
  font-weight: 600;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The button is pushed to the far end — the logical one, so it lands where a
 * reader of this direction finishes. */
.action-bar .primary {
  margin-inline-start: auto;
}

/* -- the reviewer picker --------------------------------------------------
 *
 * A native `<details>`: it opens and closes with no script, and degrades to
 * an open list. The panel is positioned above the summary because the bar is
 * at the foot of the screen and there is nowhere below it to go.
 */

.picker {
  position: relative;
}

.picker > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  cursor: pointer;
  list-style: none;
  padding: var(--s2) var(--s4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--page);
  font-weight: 500;
  min-inline-size: 12rem;
}

.picker > summary::-webkit-details-marker {
  display: none;
}

/* A caret drawn in CSS rather than a glyph, so it is direction-neutral and
 * needs no font coverage. */
.picker > summary::after {
  content: "";
  margin-inline-start: auto;
  inline-size: 0.45em;
  block-size: 0.45em;
  border-inline-end: 2px solid var(--ink-quiet);
  border-block-end: 2px solid var(--ink-quiet);
  transform: rotate(-135deg);
  transition: transform 120ms ease;
}

.picker[open] > summary::after {
  transform: rotate(45deg);
}

.picker > summary:hover {
  border-color: var(--accent);
}

.picker-panel {
  position: absolute;
  inset-block-end: calc(100% + var(--s2));
  inset-inline-start: 0;
  min-inline-size: 20rem;
  max-block-size: 55vh;
  overflow-y: auto;
  background: var(--page);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--lift), 0 8px 28px rgb(16 24 40 / 10%);
  padding: var(--s3);
}

.picker-help {
  margin-block: 0 var(--s3);
  font-size: 0.9rem;
  color: var(--ink-quiet);
  max-inline-size: none;
}

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

.picker-list label {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) var(--s3);
  border-radius: var(--radius);
  cursor: pointer;
}

.picker-list label:hover {
  background: var(--raised);
}

.picker-name {
  font-weight: 500;
}

/* The load. Pushed to the far end and set quiet: it informs the choice, it is
 * not the choice. */
.picker-load {
  margin-inline-start: auto;
  font-size: 0.88rem;
  color: var(--ink-quiet);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* The bar overlaps the end of the page, so the last rows of a table would sit
 * under it. */
body:has(.action-bar:not([hidden])) .page {
  padding-block-end: 7rem;
}

/* ---------------------------------------------------------------------------
 * Distribution — the panel under the table
 * ------------------------------------------------------------------------ */

.bulk {
  margin-block-start: var(--s5);
}

.bulk h2 {
  margin-block-start: 0;
  font-size: 1.05rem;
}

/* The count, on screen while the admin decides rather than after the refusal.
 * Reads "47 of 129 questions selected". */
.selected {
  font-weight: 600;
  color: var(--ink-quiet);
  font-variant-numeric: tabular-nums;
  margin-block: 0 var(--s4);
}

.bulk-controls {
  display: flex;
  gap: var(--s6);
  align-items: flex-start;
  flex-wrap: wrap;
}

.bulk-controls .field {
  min-inline-size: 22rem;
  margin-block-end: 0;
}

.bulk-controls select[multiple] {
  max-inline-size: none;
  padding: var(--s2);
}

.bulk-controls select[multiple] option {
  padding: var(--s2) var(--s3);
  border-radius: var(--radius);
}

/* Changing where a question goes next is a real action but not the one this
 * screen is for, so it sits below the primary and reads quieter. */
.bulk-secondary {
  display: flex;
  gap: var(--s3);
  flex-wrap: wrap;
  margin-block-start: var(--s5);
  padding-block-start: var(--s4);
  border-block-start: 1px solid var(--line);
}

/* ---------------------------------------------------------------------------
 * Upload, the import report, and export
 * ------------------------------------------------------------------------ */

.upload,
.export,
.confirm {
  display: flex;
  gap: var(--s4);
  align-items: flex-end;
  flex-wrap: wrap;
  margin-block: var(--s4) var(--s6);
}

.upload label {
  margin-block-end: 0;
}

/* Which shape the export leaves in. A choice sitting beside the two buttons,
 * not competing with them: the action is still "export these questions", and
 * this only says what the file will be. */
.formats {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding-block: var(--s2) var(--s3);
  padding-inline: var(--s4);
  background: var(--raised);
  display: flex;
  gap: var(--s4);
  align-items: center;
  flex-wrap: wrap;
}

.formats legend {
  font-weight: 600;
  font-size: 0.9rem;
  padding-inline: var(--s2);
  color: var(--ink-quiet);
}

.format {
  display: flex;
  gap: var(--s2);
  align-items: center;
  margin-block-end: 0;
  font-weight: 500;
  white-space: nowrap;
}

.format input {
  inline-size: auto;
  min-block-size: auto;
}

/* The paragraph above a findings table, saying what it means and whether it
 * blocks. The report exists to be read, so this is not decoration. */
.explain {
  color: var(--ink-quiet);
  background: var(--raised);
  border-inline-start: 3px solid var(--line-strong);
  border-radius: var(--radius);
  padding: var(--s3) var(--s4);
  max-inline-size: var(--measure);
}

.findings {
  font-size: 0.93rem;
}

.findings.error {
  border-color: color-mix(in srgb, var(--danger) 35%, transparent);
}

.findings.error thead th {
  background: var(--danger-bg);
  color: var(--danger);
}

.findings.warning thead th {
  background: var(--work-bg);
  color: var(--work);
}

.findings.notice thead th {
  background: var(--info-bg);
  color: var(--info);
}

.codes {
  list-style: none;
  margin-block: var(--s3);
  margin-inline: 0;
  padding: 0;
  display: flex;
  gap: var(--s2);
  flex-wrap: wrap;
}

.codes li {
  background: var(--raised-deep);
  border-radius: var(--radius);
  padding-inline: var(--s3);
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
 * The reviewer guide — a long read, so it gets prose treatment
 * ------------------------------------------------------------------------ */

.guide {
  max-inline-size: var(--measure);
}

.guide h2 {
  margin-block-start: var(--s7);
  padding-block-end: var(--s2);
  border-block-end: 1px solid var(--line);
}

.guide table {
  font-size: 0.94rem;
}

.guide li {
  margin-block-end: var(--s2);
}

/* The rules the guide states outright. Set apart because a reviewer skimming
 * for "what must I not change" should find them. */
.guide .rule {
  background: var(--accent-quiet);
  border-inline-start: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: var(--s3) var(--s5);
  font-weight: 600;
  max-inline-size: none;
}

/* ---------------------------------------------------------------------------
 * Narrow screens
 *
 * Not a mobile design — this is a desk tool. Enough that a laptop at 1280 and
 * a split window stay usable.
 * ------------------------------------------------------------------------ */

@media (max-width: 60rem) {
  .page {
    padding-inline: var(--s4);
  }

  main {
    padding: var(--s5) var(--s4);
  }

  .specification dl {
    grid-template-columns: 1fr;
    gap: var(--s3);
  }

  .review-actions {
    justify-content: stretch;
  }

  .review-actions button {
    flex: 1 1 12rem;
  }
}
