/* The staff portal's only stylesheet (portal.md 12.6). Design tokens are custom properties; tests/test_portal_a11y.py
   reads every text/background pair and every border and focus colour from the two schemes below and checks the WCAG
   contrast ratios (4.5:1 for text, 3:1 for interface parts), so a change here cannot slip under them. System fonts,
   no web fonts, no animation. */

/* `hidden` always hides. Without this, any rule that sets display (`.banner { display: flex }`) beats the browser's
   own `[hidden] { display: none }`, an author rule against a user-agent one, and the idle warning showed on every
   page (tests/test_portal_a11y.py checks every hidden element against the display rules). */
[hidden] { display: none !important; }

:root {
  color-scheme: light dark;
  --bg: #ffffff;
  --surface: #f4f5f7;
  --fg: #1b1f24;
  --muted: #4a5260;
  --line: #6b7280;
  --link: #0b57d0;
  --focus: #0b3d91;
  --focus-halo: #ffffff;
  --button-bg: #0b57d0;
  --button-fg: #ffffff;
  --ok: #146c2e;
  --ok-bg: #e7f4ea;
  --bad: #b3261e;
  --bad-bg: #fbeaea;
  --warn: #8a5300;
  --warn-bg: #fdf3e1;
  --info: #0b57d0;
  --info-bg: #e8f0fe;
  --space: 1rem;
  --radius: 4px;
  --measure: 42rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #121417;
    --surface: #1c1f24;
    --fg: #e8eaed;
    --muted: #b4bac4;
    --line: #8b93a1;
    --link: #8ab4f8;
    --focus: #ffd166;
    --focus-halo: #121417;
    --button-bg: #8ab4f8;
    --button-fg: #0b1a33;
    --ok: #6dd58c;
    --ok-bg: #12301b;
    --bad: #ff8a80;
    --bad-bg: #3b1513;
    --warn: #f6c26b;
    --warn-bg: #3a2a0a;
    --info: #8ab4f8;
    --info-bg: #10243f;
  }
}

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

html { font-size: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", sans-serif;
  line-height: 1.5;
}

a { color: var(--link); text-underline-offset: 0.15em; }
a:hover { text-decoration-thickness: 2px; }

/* Focus: a 3px outline in the focus colour with a halo, on every focusable element (WCAG 2.4.7, 2.4.13). */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
}
main:focus, .error-summary:focus, .banner:focus { outline: none; box-shadow: none; }
.error-summary:focus-visible, .banner:focus-visible { outline: 3px solid var(--focus); }

.skip-link {
  position: absolute;
  left: 0.5rem;
  top: -10rem;
  padding: 0.5rem 1rem;
  background: var(--bg);
  color: var(--link);
  z-index: 10;
}
.skip-link:focus { top: 0.5rem; }

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

.site-header {
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  padding: 0.5rem var(--space);
}
.header-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem var(--space);
}
.site-name { margin: 0; font-weight: 700; font-size: 1.125rem; }
.site-name a { color: var(--fg); text-decoration: none; }
.lab-name { font-weight: 400; color: var(--muted); }
.account { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem var(--space); }
.account p, .account form { margin: 0; }

nav ul { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.25rem; }
nav a {
  display: inline-block;
  min-height: 2.75rem;
  padding: 0.6rem 0.75rem;
  color: var(--fg);
  text-decoration: none;
  border-bottom: 3px solid transparent;
}
nav a:hover { text-decoration: underline; }
nav a[aria-current="page"] { border-bottom-color: var(--link); font-weight: 700; }

main { display: block; max-width: 72rem; margin: 0 auto; padding: var(--space); }
.narrow { max-width: var(--measure); }
.lead { font-size: 1.125rem; }
h1 { font-size: 1.75rem; line-height: 1.25; margin: 0.5rem 0 1rem; }
h2 { font-size: 1.25rem; margin: 1.5rem 0 0.5rem; }

.page-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space); }
.page-head form { margin: 0; }

button, .button-link {
  display: inline-block;
  min-height: 2.75rem;
  min-width: 2.75rem;
  padding: 0.55rem 1.1rem;
  border: 2px solid var(--button-bg);
  border-radius: var(--radius);
  background: var(--button-bg);
  color: var(--button-fg);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}
.button-secondary {
  background: var(--bg);
  color: var(--fg);
  border-color: var(--line);
}

.form { margin: 1rem 0 1.5rem; }
.field { margin-bottom: 1.25rem; }
label { display: block; font-weight: 600; margin-bottom: 0.25rem; }
.hint { margin: 0 0 0.25rem; color: var(--muted); }
input, select {
  display: block;
  width: 100%;
  max-width: 24rem;
  min-height: 2.75rem;
  padding: 0.5rem 0.6rem;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--fg);
  font: inherit;
}
input[aria-invalid="true"] { border-color: var(--bad); border-width: 3px; }
.input-code { max-width: 10rem; letter-spacing: 0.15em; font-variant-numeric: tabular-nums; }
.input-mono, .mono, code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.field-error { color: var(--bad); font-weight: 600; margin: 0 0 0.25rem; display: flex; gap: 0.35rem; align-items: center; }

.filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem var(--space); margin: 1rem 0; }
.filters .field { margin: 0; }
.filters input, .filters select { width: 16rem; }

.error-summary {
  border: 4px solid var(--bad);
  padding: 0.75rem var(--space);
  margin: 1rem 0;
  background: var(--bad-bg);
}
.error-summary h2 { margin-top: 0; display: flex; gap: 0.4rem; align-items: center; }
.error-summary ul { margin: 0; padding-left: 1.25rem; }
.error-summary a { color: var(--fg); font-weight: 600; }

.banner {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  border-left: 6px solid var(--info);
  background: var(--info-bg);
  color: var(--fg);
  padding: 0.6rem var(--space);
  margin: 0.75rem 0;
}
.banner p { margin: 0.15rem 0; }
.banner .icon { margin-top: 0.3rem; flex: none; }
.banner-ok { border-left-color: var(--ok); background: var(--ok-bg); }
.banner-bad { border-left-color: var(--bad); background: var(--bad-bg); }
.banner-warn { border-left-color: var(--warn); background: var(--warn-bg); }
.banner-info { border-left-color: var(--info); background: var(--info-bg); }
.idle-warning form { margin-top: 0.5rem; }

.icon { width: 1em; height: 1em; vertical-align: -0.125em; }
.state { display: inline-flex; align-items: center; gap: 0.35rem; font-weight: 600; }
.state-ok { color: var(--ok); }
.state-bad { color: var(--bad); }
.state-warn { color: var(--warn); }
.state-none { color: var(--muted); }

.verdict { display: flex; gap: 0.5rem; align-items: center; font-size: 1.25rem; font-weight: 700; margin: 1rem 0; }
.verdict-ok { color: var(--ok); }
.verdict-bad { color: var(--bad); }
.verdict-warn { color: var(--warn); }
.as-of { color: var(--muted); margin: 0 0 0.75rem; }
.count { color: var(--muted); }
.pager { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem var(--space); margin: 1rem 0; }
.pager p, .pager ul { margin: 0; }
.empty { color: var(--muted); font-style: italic; }

/* Data tables keep their table semantics on every width; a narrow screen scrolls the table, not the page
   (WCAG 1.4.10 allows two-dimensional tables to scroll). The region is focusable, so it scrolls by keyboard. */
.table-scroll { overflow-x: auto; max-width: 100%; }
.table { border-collapse: collapse; width: 100%; margin: 0.5rem 0 1rem; }
.table caption { text-align: left; font-weight: 600; padding: 0.25rem 0; caption-side: top; }
.table th, .table td { text-align: left; vertical-align: top; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--line); }
.table thead th { border-bottom-width: 2px; white-space: nowrap; }
.table tbody th { font-weight: 600; }

.section-block { margin-bottom: 2rem; }
.lines { padding-left: 1.25rem; }
.lines li { margin-bottom: 0.4rem; }
.disks { list-style: none; padding: 0; }
.disk { margin-bottom: 1.25rem; }
.disk p { margin: 0 0 0.25rem; }
meter { width: 100%; max-width: 28rem; height: 1.25rem; }

.steps { padding-left: 1.25rem; }
.steps > li { margin-bottom: 1.5rem; }
.qr-figure { margin: 0.5rem 0; }
.qr-figure svg.qr { width: 14rem; height: 14rem; display: block; background: #ffffff; padding: 0.25rem; }
.qr-figure figcaption { color: var(--muted); }
.key code { font-size: 1.125rem; letter-spacing: 0.08em; word-break: break-all; }

.site-footer {
  border-top: 1px solid var(--line);
  margin-top: 2rem;
  padding: var(--space);
  color: var(--muted);
  max-width: 72rem;
  margin-left: auto;
  margin-right: auto;
}
.session-note { display: flex; flex-wrap: wrap; gap: 0.5rem var(--space); align-items: center; }
.session-note p, .session-note form { margin: 0; }

/* Phase P2: the student's page, confirmations, results and web access (docs/PORTAL-DESIGN.md). No new colour: every
   pair below is one the contrast tests already check. */
.button-danger {
  background: var(--bg);
  color: var(--fg);
  border-color: var(--bad);
  border-width: 3px;
}
.form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem var(--space); margin-top: 0.5rem; }
fieldset { border: 0; margin: 0 0 1.25rem; padding: 0; min-width: 0; }
legend { font-weight: 600; margin-bottom: 0.25rem; padding: 0; }
.choice { display: flex; align-items: center; gap: 0.6rem; margin: 0.35rem 0; }
.choice label { display: inline; font-weight: 400; margin: 0; }
/* 24 CSS pixels at least (WCAG 2.5.8); the label beside it is part of the target. */
input[type="radio"] {
  display: inline-block;
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  min-height: 1.5rem;
  max-width: none;
  margin: 0;
  padding: 0;
  accent-color: var(--link);
}
.subtitle { display: block; font-size: 1.125rem; font-weight: 400; color: var(--muted); }
.facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.35rem 1rem; margin: 1rem 0 1.5rem; }
.facts dt { font-weight: 600; }
.facts dd { margin: 0; }
.actions { list-style: none; padding: 0; margin: 0; }
.action { border: 1px solid var(--line); border-radius: var(--radius); padding: 0.75rem var(--space); margin-bottom: 0.75rem; }
.action h3 { margin: 0 0 0.25rem; font-size: 1.0625rem; }
.action p { margin: 0 0 0.6rem; }
.danger-zone { border-left: 6px solid var(--bad); padding-left: var(--space); margin-top: 2rem; }
.result-heading { display: flex; gap: 0.5rem; align-items: center; }
.result-heading:focus { outline: none; box-shadow: none; }
.result-heading:focus-visible { outline: 3px solid var(--focus); }
.secret-box { border: 2px solid var(--line); border-radius: var(--radius); padding: 0 var(--space) 0.75rem; margin: 1rem 0; }
.secret-box summary { cursor: pointer; font-weight: 600; min-height: 2.75rem; padding: 0.6rem 0; }
.secret {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1.75rem;
  letter-spacing: 0.12em;
  word-break: break-all;
  padding: 0.4rem 0.75rem;
  margin: 0.25rem 0 0.75rem;
  background: var(--surface);
  color: var(--fg);
  border: 1px solid var(--line);
}
.spelled { columns: 12rem; padding-left: 2rem; }
.copy-status, .working { font-weight: 600; margin: 0.5rem 0; }
.state-line { margin: 0.25rem 0; }

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

@media (forced-colors: active) {
  :focus-visible { outline: 3px solid CanvasText; box-shadow: none; }
  .banner, .error-summary { border: 2px solid CanvasText; }
  .icon { forced-color-adjust: auto; }
  nav a[aria-current="page"] { border-bottom-color: Highlight; }
  /* The system's own button colours: Chromium forces a button's background but not its custom text colour, which
     axe-core measured at 1.2:1 in the dark scheme (scripts/portal_a11y.py, 2026-11-02). */
  button, .button-link { forced-color-adjust: none; background: ButtonFace; color: ButtonText; border-color: ButtonText; }
}
