/* RoboAlarms firmware server: the one stylesheet of its public and admin pages (FWS-074), each admin area's
 * own (static/areas) served after it. Its look started in the mockups (docs/mockup, the earlier design's
 * record); docs/ADMIN-UX.md describes the shared pieces the admin pages draw with it. The RoboAlarms
 * identity as the website, the manual and the Flasher use it: teal #007b7d on light pages and #94eff0 on
 * dark ones, the Segoe UI system stack, 7px buttons, 4px tags and 12px hairline cards. The pages follow
 * the computer's light or dark setting. Nothing flashes, pulses or animates: state is colour, words and
 * symbols. */

:root {
  color-scheme: light;
  --bg: #f7faf9;
  --surface: #ffffff;
  --surface-raised: #edf3f2;
  --soft: #eef4f2;
  --ink: #142b30;
  --muted: #536970;
  --faint: #7a8e92;
  --line: #d3dfdd;
  --line-strong: #b9cac7;
  --accent: #007b7d;
  --accent-strong: #006668;
  --accent-bg: #e0f3ef;
  --button-ink: #ffffff;
  --amber: #865914;
  --amber-bg: #fbf1de;
  --red: #b3261e;
  --red-bg: #fdecea;
  --red-ink: #ffffff;
  --shadow: 0 10px 30px rgb(20 43 48 / 14%);
  --s1: #2a78d6;
  --s2: #eb6834;
  --s3: #1baf7a;
  --radius: 12px;
  --font: 'Segoe UI', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  --mono: ui-monospace, 'Cascadia Code', Consolas, 'SF Mono', Menlo, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    color-scheme: dark;
    --bg: #111719;
    --surface: #172023;
    --surface-raised: #1c282b;
    --soft: #151d20;
    --ink: #f3f7f6;
    --muted: #a5b5b8;
    --faint: #7d8f93;
    --line: #2a373b;
    --line-strong: #3a4b50;
    --accent: #94eff0;
    --accent-strong: #17bec2;
    --accent-bg: #17393b;
    --button-ink: #093335;
    --amber: #f0cf8f;
    --amber-bg: #2c2517;
    --red: #ff8a80;
    --red-bg: #3a1d1b;
    --red-ink: #2a0d0b;
    --shadow: 0 10px 30px rgb(0 0 0 / 45%);
    --s1: #3987e5;
    --s2: #d95926;
    --s3: #199e70;
  }
}
:root[data-theme='dark'] {
  color-scheme: dark;
  --bg: #111719;
  --surface: #172023;
  --surface-raised: #1c282b;
  --soft: #151d20;
  --ink: #f3f7f6;
  --muted: #a5b5b8;
  --faint: #7d8f93;
  --line: #2a373b;
  --line-strong: #3a4b50;
  --accent: #94eff0;
  --accent-strong: #17bec2;
  --accent-bg: #17393b;
  --button-ink: #093335;
  --amber: #f0cf8f;
  --amber-bg: #2c2517;
  --red: #ff8a80;
  --red-bg: #3a1d1b;
  --red-ink: #2a0d0b;
  --shadow: 0 10px 30px rgb(0 0 0 / 45%);
  --s1: #3987e5;
  --s2: #d95926;
  --s3: #199e70;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; font: 15px/1.6 var(--font); color: var(--ink); background: var(--bg); }
a { color: var(--accent); text-underline-offset: 2px; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
::selection { background: var(--accent); color: var(--bg); }
h1, h2, h3, p { margin: 0; }
h1 { font-size: 26px; line-height: 1.25; font-weight: 700; letter-spacing: -.02em; }
h2 { font-size: 17px; line-height: 1.35; font-weight: 650; }
h3 { font-size: 17px; line-height: 1.35; font-weight: 650; margin-bottom: 8px; }
.mono { font-family: var(--mono); font-size: 12.5px; }
.muted { color: var(--muted); }
.faint { color: var(--faint); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* App bar: the website's header and wordmark */
.appbar { display: flex; align-items: center; gap: 16px; padding: 10px 20px; min-height: 64px; background: var(--bg); border-bottom: 1px solid var(--line); }
.wordmark { display: flex; align-items: center; gap: 10px; margin-right: auto; color: var(--ink); text-decoration: none; }
.wordmark img { width: 32px; height: 32px; object-fit: contain; }
.wordmark b { font-size: 21px; font-weight: 750; letter-spacing: -.055em; }
.wordmark span { color: var(--muted); font-size: 15px; padding-left: 12px; border-left: 1px solid var(--line); }
.who { display: flex; align-items: center; gap: 12px; font-size: 14px; color: var(--muted); }
.who a { color: var(--ink); font-weight: 650; text-decoration: none; }
.who a:hover { text-decoration: underline; }
.who form { margin: 0; }

/* Side menu and page */
.shell { display: grid; grid-template-columns: 236px minmax(0, 1fr); min-height: calc(100vh - 64px); }
.sidemenu { padding: 20px 12px; border-right: 1px solid var(--line); }
.sidemenu .group + .group { margin-top: 20px; }
.sidemenu .label { display: block; padding: 0 10px 4px; font-size: 12.5px; font-weight: 650; color: var(--faint); }
.sidemenu a { display: block; padding: 7px 10px; border-radius: 7px; color: var(--ink); font-size: 14.5px; text-decoration: none; }
.sidemenu a:hover { background: var(--surface-raised); }
.sidemenu a[aria-current='page'] { background: var(--accent-bg); color: var(--accent); font-weight: 650; }
main { padding: 28px 32px 56px; max-width: 1180px; }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px 24px; flex-wrap: wrap; margin-bottom: 22px; }
.page-head p { margin-top: 6px; max-width: 64ch; color: var(--muted); }
.footnote { margin-top: 12px; font-size: 13.5px; color: var(--muted); }

/* Buttons: 7px corners */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 38px; padding: 0 14px; border: 1px solid var(--line-strong); border-radius: 7px; background: var(--surface); color: var(--ink); font: 600 14px/1.2 var(--font); text-decoration: none; white-space: nowrap; cursor: pointer; }
.btn:hover { background: var(--surface-raised); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--button-ink); }
.btn.primary:hover { background: var(--accent-strong); border-color: var(--accent-strong); }
.btn.danger { background: var(--red); border-color: var(--red); color: var(--red-ink); }
.btn.small { min-height: 32px; padding: 0 11px; font-size: 13.5px; }

/* Tags: 4px corners, always words, never colour alone */
.tags { display: flex; flex-wrap: wrap; gap: 6px; }
.tag { display: inline-flex; align-items: center; padding: 0 8px; border: 1px solid var(--line); border-radius: 4px; background: var(--soft); color: var(--muted); font-size: 12.5px; font-weight: 600; line-height: 22px; white-space: nowrap; }
.tag.good { background: var(--accent-bg); border-color: transparent; color: var(--accent); }
.tag.warn { background: var(--amber-bg); border-color: transparent; color: var(--amber); }
.tag.bad { background: var(--red-bg); border-color: transparent; color: var(--red); }

/* Cards: 12px hairline */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.dialog { padding: 20px 22px; }
.dialog p + p, .dialog p + .linkbox, .dialog .linkbox + p { margin-top: 10px; }
.actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; margin-top: 20px; }

/* Lists */
.list { width: 100%; border-collapse: collapse; }
.list th { padding: 11px 18px; border-bottom: 1px solid var(--line); text-align: left; font-size: 12.5px; font-weight: 650; color: var(--muted); }
.list td { padding: 14px 18px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.list tbody tr:last-child td { border-bottom: 0; }
.list td small { display: block; color: var(--faint); font-size: 12.5px; }
.list .row-actions { width: 1%; text-align: right; white-space: nowrap; }
.person { display: flex; align-items: center; gap: 12px; min-width: 0; }
.person b { display: flex; align-items: center; gap: 8px; font-weight: 650; }
.person small { color: var(--muted); font-size: 13.5px; overflow-wrap: anywhere; }
.avatar { display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: 50%; background: var(--accent-bg); color: var(--accent); font-weight: 700; }

/* Forms */
.field { display: grid; gap: 6px; margin-bottom: 16px; }
.field label { font-size: 14px; font-weight: 650; }
.field input, .field select { height: 40px; padding: 0 12px; border: 1px solid var(--line-strong); border-radius: 7px; background: var(--surface); color: var(--ink); font: 15px var(--font); }
.field select { padding: 0 8px; min-width: 0; }
.field > input, .field > select, .field > textarea { width: 100%; min-width: 0; }
.field .hint { font-size: 13px; color: var(--muted); }
.linkbox { padding: 10px 12px; border: 1px solid var(--line-strong); border-radius: 7px; background: var(--soft); font: 13px/1.5 var(--mono); overflow-wrap: anywhere; user-select: all; }

/* Notices */
.notice { padding: 12px 16px; border-radius: 10px; font-size: 14.5px; }
.notice.warn { background: var(--amber-bg); }
.notice.warn b { color: var(--amber); }

/* Public download page (FWS-060): one column, no side menu */
main.site { max-width: 960px; margin: 0 auto; padding: 28px 16px 48px; }
.site .lede { margin-top: 6px; color: var(--muted); }
.finder { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px 16px; align-items: end; margin-top: 20px; padding: 18px 20px; }
.finder .field { margin: 0; }
.site .help { margin-top: 10px; font-size: 13.5px; color: var(--muted); }
.results-head { margin: 28px 0 12px; }
.release { padding: 16px 20px 8px; }
.release + .release { margin-top: 14px; }
.release-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.release-date { margin-left: auto; color: var(--muted); font-size: 14px; }
.release-notes { margin-top: 6px; color: var(--muted); }

/* Tabs that split a busy admin page into its parts: links, each tab its own address, so they work without
 * JavaScript and a Save returns to its tab. The current one is marked with aria-current="page". */
.tabs { display: flex; flex-wrap: wrap; gap: 0 2px; margin-top: 4px; border-bottom: 1px solid var(--line); }
.tabs > a { margin-bottom: -1px; padding: 9px 14px; border-bottom: 2px solid transparent; color: var(--muted); font-size: 15px; font-weight: 650; white-space: nowrap; text-decoration: none; }
.tabs > a:hover { color: var(--ink); }
.tabs > a[aria-current='page'] { border-bottom-color: var(--accent); color: var(--accent); }
.tabs .count { margin-left: 4px; padding: 0 6px; border-radius: 4px; background: var(--soft); color: var(--muted); font-size: 12.5px; }
.tabs .count.warn { background: var(--amber-bg); color: var(--amber); }
.choices { display: grid; gap: 8px; }
.choices .check { margin: 0; font-weight: 600; }
.choices .check small { font-weight: 400; }
.choices .inline { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.choices .inline input[type='date'] { width: auto; height: auto; margin: 0; }
.choices .inline input[type='radio'] { margin: 0; }
.preview { margin-top: 16px; padding: 12px 14px; border-radius: 8px; background: var(--soft); font-size: 14.5px; }
.preview b { font-variant-numeric: tabular-nums; }
.more-filters { grid-column: 1 / -1; }
.more-filters > summary { color: var(--accent); font-size: 14.5px; font-weight: 600; cursor: pointer; }
.more-filters[open] > summary { margin-bottom: 12px; }
.more-filters > div { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px 16px; }
.empty { padding: 18px 20px; color: var(--muted); }
.empty .btn { margin-top: 10px; }
.site-foot { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 40px; padding-top: 18px; border-top: 1px solid var(--line); font-size: 13.5px; }

/* Sign-in pages: one card, no menu */
.auth { max-width: 420px; margin: 0 auto; padding: 48px 16px 40px; }
.auth-brand { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 22px; color: var(--ink); text-decoration: none; }
.auth-brand img { width: 36px; height: 36px; }
.auth-brand b { font-size: 23px; font-weight: 750; letter-spacing: -.055em; }
.auth-brand span { color: var(--muted); padding-left: 12px; border-left: 1px solid var(--line); }
.auth .card { padding: 26px 24px; }
.auth h1 { font-size: 22px; margin-bottom: 6px; }
.auth .lead { margin-bottom: 18px; color: var(--muted); }
.btn.block { width: 100%; min-height: 42px; }
.auth-links { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; margin-top: 14px; font-size: 14px; }
.auth-foot { margin-top: 18px; font-size: 13px; color: var(--muted); text-align: center; }
.code-input { font: 600 24px/1 var(--mono) !important; letter-spacing: .3em; text-align: center; }
.notice.bad { background: var(--red-bg); }
.notice.bad b { color: var(--red); }
.notice.info { background: var(--accent-bg); }
.notice + .card, .notice + form { margin-top: 12px; }

/* Admin sections: a card per group, saved on its own */
.section { padding: 20px 22px; }
.section + .section, .card + .section { margin-top: 16px; }
.section-head { margin-bottom: 16px; }
.section-head p { margin-top: 4px; color: var(--muted); font-size: 14.5px; max-width: 70ch; }
.section-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 10px 14px; margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.section-foot .muted { margin-right: auto; font-size: 13.5px; }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0 16px; }
.field textarea { min-height: 140px; padding: 10px 12px; border: 1px solid var(--line-strong); border-radius: 7px; background: var(--surface); color: var(--ink); font: 14px/1.55 var(--mono); resize: vertical; }
.field input[readonly] { background: var(--soft); color: var(--muted); }
.check { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 12px; font-size: 14.5px; }
.check input { width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--accent); flex: none; }
.check small { display: block; color: var(--muted); font-size: 13px; }
/* A row of a card with its own action on the right: a second step, a signed-in browser */
.danger-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 20px; }
.danger-row + .danger-row { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.danger-row p { max-width: 62ch; color: var(--muted); font-size: 14.5px; }
dl.kv { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 18px; margin: 0; font-size: 14.5px; }
dl.kv dt { color: var(--muted); }
dl.kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.hash { font: 12.5px/1.5 var(--mono); overflow-wrap: anywhere; color: var(--muted); }

.crumbs { margin-bottom: 4px; font-size: 14px; color: var(--muted); }
fieldset.field { margin: 0 0 12px; padding: 0; border: 0; min-width: 0; }
fieldset.field legend { padding: 0; margin-bottom: 6px; }
fieldset.field > legend:not(.hint) { font-size: 14px; font-weight: 650; }
fieldset.field .check { margin-bottom: 6px; }
.page-head h1 .tag { vertical-align: 5px; margin-left: 6px; }
pre.cmd { margin: 6px 0 0; padding: 10px 12px; border-radius: 7px; background: var(--soft); border: 1px solid var(--line); font: 13px/1.5 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; }

/* Filters shown as a row of choices, each a link */
.seg { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.seg a { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border: 1px solid var(--line-strong); border-radius: 7px; color: var(--ink); font-size: 14px; font-weight: 600; text-decoration: none; }
.seg a:hover { background: var(--surface-raised); }
.seg a[aria-current='page'] { border-color: var(--accent); background: var(--accent-bg); color: var(--accent); }
.seg .n { color: var(--muted); font-weight: 500; font-variant-numeric: tabular-nums; }
/* The board picker (docs/ADMIN-UX.md, Releases "List"): in place of board chips from 7 boards, a GET form of
 * a field (its label beside the select, both as every form draws them) and Show, on one row above the
 * page's other chips. Below 720 px the label goes above the select, which spans the width, and Show sits
 * under it. */
.board-pick { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin-bottom: 14px; }
.board-pick .field { display: flex; align-items: center; gap: 10px; min-width: 0; max-width: 100%; margin: 0; }
.board-pick .field select { width: auto; min-width: 16rem; max-width: 100%; }
.table-wrap { position: relative; overflow-x: auto; } /* relative: a screen-reader text inside stays in the scroll */
.list td.num, .list th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Upload */
.dropzone { display: grid; place-items: center; gap: 6px; padding: 26px 16px; border: 2px dashed var(--line-strong); border-radius: 10px; background: var(--soft); text-align: center; color: var(--muted); }
.dropzone b { color: var(--ink); }
.checklist { margin: 0; padding: 0; list-style: none; font-size: 14.5px; }
.checklist li { display: flex; gap: 10px; padding: 6px 0; }
.checklist .mark { flex: none; width: 20px; text-align: center; font-weight: 700; }
.checklist .ok .mark { color: var(--accent); }
.timeline { margin: 0; padding: 0; list-style: none; font-size: 14px; }
.timeline li { display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 12px; padding: 7px 0; border-top: 1px solid var(--line); }
.timeline li:first-child { border-top: 0; }
.timeline time { color: var(--muted); font-variant-numeric: tabular-nums; }

/* Audit entries: a line that opens to its details */
.entries { overflow: hidden; }
.entry-line, .entries-head { display: grid; grid-template-columns: 160px 130px minmax(0, 1.2fr) minmax(0, 1.4fr) 90px; gap: 12px; align-items: center; padding: 10px 18px; font-size: 14px; }
.entries-head { border-bottom: 1px solid var(--line); color: var(--muted); font-size: 12.5px; font-weight: 650; }
.entry { border-bottom: 1px solid var(--line); }
.entry:last-child { border-bottom: 0; }
.entry > summary { list-style: none; cursor: pointer; }
.entry > summary::-webkit-details-marker { display: none; }
.entry > summary:hover { background: var(--surface-raised); }
.entry[open] > summary { background: var(--soft); }
.entry-line > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.entry-line time { font-variant-numeric: tabular-nums; color: var(--muted); }
.entry-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 16px 28px; padding: 14px 18px 18px; background: var(--soft); }
.entry-body h4 { margin: 0 0 8px; font-size: 12.5px; color: var(--faint); font-weight: 650; }
.diff { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.diff th, .diff td { padding: 5px 8px; border: 1px solid var(--line); text-align: left; vertical-align: top; overflow-wrap: anywhere; }
.diff th { color: var(--muted); font-weight: 650; }
.diff th:first-child, .diff td:first-child { overflow-wrap: normal; }
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin-top: 12px; font-size: 14px; color: var(--muted); }

/* Stats: charts drawn on the server as SVG, each with its table */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 16px; }
.tile { padding: 14px 18px; }
.tile small { display: block; color: var(--muted); font-size: 13px; }
.tile b { display: block; margin-top: 2px; font-size: 26px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.tile span { font-size: 13px; color: var(--muted); }
.chart { padding: 18px 20px 14px; }
.chart + .chart, .chart-grid + .chart, .chart + .chart-grid { margin-top: 16px; }
.chart-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr)); gap: 16px; }
.chart-grid > .chart { margin-top: 0; }
.chart-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 16px; margin-bottom: 10px; }
.chart-head p { color: var(--muted); font-size: 13.5px; }
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.plot { overflow-x: auto; }
.chart svg text { fill: var(--muted); font: 12px var(--font); }
.chart .grid line { stroke: var(--line); stroke-width: 1; }
.chart .axis { stroke: var(--line-strong); stroke-width: 1; }
.chart .line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; }
.chart .area-fill { fill: var(--accent); opacity: .1; }
.chart .end { fill: var(--accent); stroke: var(--surface); stroke-width: 2; }
.chart text.end-label { fill: var(--ink); font-weight: 650; }
.chart .mark-line { stroke: var(--faint); stroke-width: 1; stroke-dasharray: 3 3; }
.chart .hit { fill: transparent; }
.chart .s1 { fill: var(--s1); } .chart .s2 { fill: var(--s2); } .chart .s3 { fill: var(--s3); }
.chart text.flag { fill: var(--amber); font-weight: 650; }
.legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 0 0 8px; padding: 0; list-style: none; font-size: 13px; color: var(--muted); }
.legend i { display: inline-block; width: 10px; height: 10px; margin-right: 6px; border-radius: 3px; vertical-align: -1px; }
.table-view { margin-top: 10px; font-size: 13.5px; }
.table-view summary { cursor: pointer; color: var(--accent); font-weight: 600; }
.table-view .list td, .table-view .list th { padding: 6px 10px; }
.mix-group + .mix-group { margin-top: 16px; }
.mix-group h4 { margin: 0 0 8px; font-size: 12.5px; color: var(--faint); font-weight: 650; }

/* Profile */
.qr { display: block; width: 148px; height: 148px; padding: 8px; border-radius: 8px; background: #fff; }
.secret { font: 600 14px/1.5 var(--mono); letter-spacing: .08em; overflow-wrap: anywhere; }
.codes { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 6px 14px; padding: 12px 14px; border: 1px solid var(--line-strong); border-radius: 7px; background: var(--soft); font: 14px/1.6 var(--mono); }
.setup-grid { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 16px 22px; align-items: start; }

@media (max-width: 720px) {
  .plot svg { min-width: 600px; }
}
@media (max-width: 560px) {
  .timeline li { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .setup-grid { grid-template-columns: minmax(0, 1fr); }
  .section, .chart { padding: 16px; }
  .auth { padding-top: 28px; }
  .auth .card { padding: 22px 18px; }
  .head-actions { flex-basis: 100%; }
  .page-head .btn { width: 100%; }
  .section-foot .btn { flex: 1; }
  .tabs > a { padding: 9px 10px; font-size: 14.5px; }
}
@media (max-width: 900px) {
  .entry-line, .entries-head { grid-template-columns: 136px minmax(0, 1fr) 80px; }
  .entry-line .who, .entry-line .target, .entries-head .who, .entries-head .target { display: none; }
  .entry-body { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 900px) {
  .shell { grid-template-columns: minmax(0, 1fr); align-content: start; }
  .sidemenu { display: flex; gap: 4px; padding: 8px 16px; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--line); white-space: nowrap; }
  .sidemenu .group { display: contents; }
  .sidemenu .label { display: none; }
  main { padding: 22px 16px 48px; }
}
@media (max-width: 720px) {
  .appbar { padding: 8px 16px; gap: 10px; }
  .wordmark span, .who-label { display: none; }
  .list thead { display: none; }
  .list, .list tbody, .list tr, .list td { display: block; width: 100%; }
  .list tr { padding: 14px 16px; border-bottom: 1px solid var(--line); }
  .list tbody tr:last-child { border-bottom: 0; }
  .list td { padding: 3px 0; border: 0; }
  .list td.num { text-align: left; }
  .list td[data-label]::before { content: attr(data-label); display: block; font-size: 12px; color: var(--faint); }
  .list td:first-child::before { display: none; }
  .list .row-actions { width: auto; padding-top: 10px; text-align: left; }
  .board-pick .field { display: grid; flex: 1 1 100%; gap: 6px; }
  .board-pick .field select { width: 100%; min-width: 0; }
}

/* What the built pages added to the mockups' rules: their inline styles as classes, since the pages'
 * Content-Security-Policy allows no inline style. */
.auth .card > p + p { margin-top: 10px; }
.auth .card > p + .field, .auth .card > .muted + .field { margin-top: 14px; }
.auth .card .notice { margin-bottom: 16px; }
.auth .card .btn + .btn { margin-top: 10px; }
.auth .codes { margin: 4px 0 18px; }
.auth .secret { margin: 8px 0 14px; }
.code-input.long { font-size: 17px !important; letter-spacing: .06em; }
.linkbutton { padding: 0; border: 0; background: none; color: var(--accent); font: inherit; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.notice a { color: inherit; }
.release-head h1 { margin: 0 6px 0 0; }
.site .crumbs { margin-bottom: 6px; }
.site .section { margin-top: 18px; }
.site .section + .help { margin-top: 14px; }
/* The download page (FWS-060): the Flasher's table, then the firmware of one board, each release's files in
 * one table grouped by kind (a tbody each, its rowgroup header first, drawn as every list's row groups
 * below); a release's notes page keeps its own look. */
.dl-section { margin-top: 30px; }
.dl-head { font-size: 20px; line-height: 1.3; }
.dl-head + .help { margin-top: 4px; }
.dl-section > .finder, .dl-section > .empty { margin-top: 12px; }
.dl-card { margin-top: 12px; overflow: hidden; }
.results-head { font-size: 17px; line-height: 1.35; font-weight: 650; }
.release { padding: 16px 0 0; overflow: hidden; }
.release > .release-head, .release > .release-notes { padding: 0 20px; }
.release-head h4 { margin: 0 6px 0 0; font-size: 20px; line-height: 1.3; }
.dl-files { margin-top: 12px; border-top: 1px solid var(--line); }
.list.dl-table tbody th[scope='row'] { vertical-align: middle; }
.dl-files thead th:first-child { width: 32%; }
.dl-table th[scope='row'] .tag { margin-left: 6px; vertical-align: 1px; }
.dl-table td small { overflow-wrap: anywhere; }
.dl-table .dl-get { width: 1%; text-align: right; white-space: nowrap; }
@media (max-width: 720px) {
  .dl-table .dl-get { width: 100%; padding-top: 10px; text-align: left; }
  .dl-table .dl-get .btn { width: 100%; }
  .release > .release-head, .release > .release-notes { padding: 0 16px; }
}
.prose { overflow-wrap: anywhere; }
.prose > * + * { margin-top: 12px; }
.prose h2, .prose h3, .prose h4 { margin-top: 22px; }
.prose > :first-child { margin-top: 0; }
.prose h4 { font-size: 15px; font-weight: 650; }
.prose ul, .prose ol { margin-bottom: 0; padding-left: 22px; }
.prose li + li { margin-top: 4px; }
.prose code { padding: 1px 5px; border-radius: 4px; background: var(--soft); font: 13px var(--mono); }
.prose pre { margin-bottom: 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: 7px; background: var(--soft); overflow-x: auto; font: 13px/1.5 var(--mono); }
.prose pre code { padding: 0; background: none; }
.prose dl.kv { margin-top: 12px; }
.prose hr { height: 0; margin: 20px 0 0; border: 0; border-top: 1px solid var(--line); }
/* The passkey step's button stays disabled until the passkey script enables it. */
.btn:disabled { opacity: .5; cursor: not-allowed; }
.auth .card [data-passkey-error] { margin: 0 0 14px; }

/* The admin shell (docs/ADMIN-UX.md "Navigation" and "Page anatomy"): the side menu's counts, the Menu
 * button that takes the side menu's place below 900 px, and the shared pieces every admin page draws. */
.appbar { position: relative; }
.appmenu { display: none; }
.appmenu > summary { list-style: none; }
.appmenu > summary::-webkit-details-marker { display: none; }
.appmenu-list { position: absolute; top: calc(100% + 6px); left: 16px; right: 16px; z-index: 20; display: grid; gap: 14px; max-height: calc(100vh - 90px); padding: 12px 8px; overflow-y: auto; background: var(--surface); border: 1px solid var(--line-strong); border-radius: 10px; box-shadow: var(--shadow); }
.appmenu-list .label { display: block; padding: 0 10px 4px; font-size: 12.5px; font-weight: 650; color: var(--faint); }
.appmenu-list a { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 40px; padding: 8px 10px; border-radius: 7px; color: var(--ink); font-size: 15px; text-decoration: none; }
.appmenu-list a:hover { background: var(--surface-raised); }
.appmenu-list a[aria-current='page'] { background: var(--accent-bg); color: var(--accent); font-weight: 650; }
.sidemenu a { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.menu-badge { flex: none; min-width: 22px; padding: 0 7px; border-radius: 11px; background: var(--soft); color: var(--muted); font-size: 12.5px; font-weight: 650; line-height: 20px; text-align: center; font-variant-numeric: tabular-nums; }
.menu-badge.warn { background: var(--amber-bg); color: var(--amber); }
.menu-badge.bad { background: var(--red-bg); color: var(--red); }

/* The page head: crumbs (the page itself isn't a link), one notice, title and tags, lead, actions */
nav.crumbs ol { display: flex; flex-wrap: wrap; margin: 0; padding: 0; list-style: none; }
nav.crumbs li + li::before { content: '\203A'; margin: 0 8px; color: var(--faint); }
nav.crumbs [aria-current='page'] { color: var(--ink); }
.crumbs + .notice { margin-top: 8px; }
.notice + .page-head { margin-top: 14px; }
.head-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.tag.info { background: var(--surface); border-color: var(--accent); color: var(--accent); }

/* The lifecycle strip: Draft, Alpha, Beta, Stable (or Withdrawn as the end), each with its date and who */
.lifecycle { display: flex; flex-wrap: wrap; gap: 10px 6px; margin: 0 0 18px; padding: 0; list-style: none; font-size: 14px; }
.lifecycle li { position: relative; flex: 1 1 110px; min-width: 0; padding-top: 10px; border-top: 3px solid var(--line); }
.lifecycle b { display: block; font-weight: 650; }
.lifecycle small { display: block; color: var(--muted); font-size: 13px; }
.lifecycle li.done { border-top-color: var(--accent); }
.lifecycle li.current { border-top-color: var(--accent); }
.lifecycle li.current::before { content: ''; position: absolute; top: -7px; left: 0; width: 11px; height: 11px; border-radius: 50%; background: var(--accent); }
.lifecycle li.current b { color: var(--accent); }
.lifecycle li.todo b, .lifecycle li.skipped b { color: var(--faint); font-weight: 600; }
.lifecycle li.skipped { border-top-style: dashed; }
.lifecycle li.withdrawn { border-top-color: var(--red); }
.lifecycle li.withdrawn b { color: var(--red); }

/* The attention list: the severity word, one sentence and one link */
.attention { margin: 0; padding: 0; list-style: none; font-size: 14.5px; }
.attention li { display: flex; align-items: baseline; gap: 12px; padding: 12px 20px; border-top: 1px solid var(--line); }
.attention li:first-child { border-top: 0; }
.attention .tag { flex: none; min-width: 78px; justify-content: center; }
.attention p { min-width: 0; }
.attention p a { white-space: nowrap; }

/* The summary list: key, value, an optional Change link */
dl.summary { margin: 0; font-size: 14.5px; }
dl.summary > div { display: grid; grid-template-columns: minmax(120px, 200px) minmax(0, 1fr) auto; gap: 2px 18px; padding: 10px 0; border-top: 1px solid var(--line); }
dl.summary > div:first-child { border-top: 0; }
dl.summary dt { color: var(--muted); }
dl.summary dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
dl.summary dd.summary-change { text-align: right; }

/* The check page: what will change, the blocking problems first, the warnings, then the action and Cancel */
.check-page { max-width: 720px; padding: 22px 24px; }
.check-page h2 { margin-bottom: 10px; }
.check-page > p + p, .check-page > p + ul, .check-page > ul + p, .check-page > dl + p { margin-top: 10px; }
.check-list { margin: 12px 0 0; padding: 0; list-style: none; font-size: 14.5px; }
.check-list li { padding: 8px 12px; border-left: 3px solid var(--line-strong); border-radius: 0 6px 6px 0; }
.check-list li + li { margin-top: 6px; }
.check-list li.bad { border-left-color: var(--red); background: var(--red-bg); }
.check-list li.warn { border-left-color: var(--amber); background: var(--amber-bg); }
.check-list li.ok { border-left-color: var(--accent); }
.check-page .actions { margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--line); }

/* The empty state, short hashes, inline row links, row headers of a list */
.empty p { max-width: 64ch; }
span.hash[title] { white-space: nowrap; text-decoration: underline dotted var(--faint); text-underline-offset: 3px; cursor: help; }
.row-links { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px 14px; font-size: 14px; }
.row-links a { white-space: nowrap; }
.list tbody th[scope='row'] { padding: 14px 18px; border-bottom: 1px solid var(--line); color: var(--ink); font-size: 14.5px; font-weight: 650; vertical-align: top; }
.list tbody tr:last-child th[scope='row'] { border-bottom: 0; }
.list tbody th[scope='row'] a { color: inherit; }
/* A list's row groups, a tbody each with its rowgroup header first (a release's files by kind, on the admin
 * and the download page alike): a soft band in sentence case */
.list th[scope='rowgroup'] { padding: 9px 18px 7px; border-bottom: 1px solid var(--line); background: var(--soft); color: var(--muted); font-size: 12.5px; font-weight: 600; text-align: left; }
.list tbody + tbody th[scope='rowgroup'] { border-top: 1px solid var(--line); }
/* A row that belongs to the one above it: a voice under its language (FWS-017, a release's "Languages and
 * voices" on the admin and the download page alike), indented, with a line down its left */
.list tr.sub-row > th[scope='row'] { padding-left: 42px; background: linear-gradient(var(--line-strong), var(--line-strong)) 26px 0 / 2px 100% no-repeat; }

/* A refused field: the reason under its label (and the hint, when that comes before the field) and right
 * above the field, which is marked red too. Inside the label or legend when the field's problems are read
 * with it (the catalogue's forms). */
.field-error { display: block; margin: 2px 0 6px; color: var(--red); font-size: 13.5px; font-weight: 600; }
.field > .field-error { margin: -4px 0 0; }
label > .field-error, legend > .field-error { margin-bottom: 0; }
.field [aria-invalid='true'] { border-color: var(--red); }
.check input[aria-invalid='true'] { outline: 2px solid var(--red); outline-offset: 1px; }

/* A card's head: its heading with a line under it (a div), and the card's own button on the right */
.card-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 10px 20px; padding: 18px 20px 12px; }
.card-head > div { flex: 1 1 320px; min-width: 0; }
.card-head p { margin-top: 4px; max-width: 70ch; color: var(--muted); font-size: 14px; }

/* Choice cards: a bordered card per choice with a round marker, the chosen one tinted. Real radios (in a
 * label each), or links that choose by their address, the current one marked with aria-current. */
.choice-cards { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.choice-cards label, .choice-cards a { display: flex; align-items: flex-start; gap: 12px; margin: 0; padding: 10px 14px; border: 1px solid var(--line-strong); border-radius: 8px; color: var(--ink); font-size: 14.5px; text-decoration: none; cursor: pointer; }
.choice-cards input[type='radio'], .choice-cards a::before { flex: none; width: 14px; height: 14px; margin: 5px 0 0; }
.choice-cards input[type='radio'] { accent-color: var(--accent); }
.choice-cards a::before { content: ''; box-sizing: border-box; border: 2px solid var(--line-strong); border-radius: 50%; }
.choice-cards label:hover, .choice-cards a:hover { background: var(--surface-raised); }
.choice-cards label:has(input:checked), .choice-cards a[aria-current] { border-color: var(--accent); background: var(--accent-bg); }
.choice-cards a[aria-current]::before { border: 4px solid var(--accent); }
.choice-cards b { font-weight: 650; }
.choice-cards small { display: block; color: var(--muted); font-size: 13px; font-weight: 400; }
.choice-cards small + small { margin-top: 4px; }

/* A feed of audit entries: time, who, what, the target (linked when it has a page) */
.feed { margin: 0; padding: 0; list-style: none; font-size: 14px; }
.feed li { display: grid; grid-template-columns: 150px 140px minmax(0, 1fr) minmax(0, 1fr); gap: 2px 12px; padding: 9px 20px; border-top: 1px solid var(--line); }
.feed li:first-child { border-top: 0; }
.section .feed li { padding-left: 0; padding-right: 0; }
.feed time { color: var(--muted); font-variant-numeric: tabular-nums; }
.feed span { min-width: 0; overflow-wrap: anywhere; }
.feed .feed-who { font-weight: 600; }

@media (max-width: 900px) {
  .appmenu { display: block; }
  .shell .sidemenu { display: none; }
}
@media (max-width: 720px) {
  .list tbody th[scope='row'] { display: block; width: 100%; padding: 0 0 4px; border: 0; }
  .list .row-links { justify-content: flex-start; }
  .list tr:has(> th[scope='rowgroup']) { padding: 0; border-bottom: 0; }
  .list th[scope='rowgroup'] { display: block; width: 100%; padding: 9px 16px 7px; }
  .list tr.sub-row { padding-left: 34px; background: linear-gradient(var(--line-strong), var(--line-strong)) 20px 0 / 2px 100% no-repeat; }
  .list tr.sub-row > th[scope='row'] { padding-left: 0; background: none; }
  .card-head { padding-left: 16px; padding-right: 16px; }
  .card-head .btn { width: 100%; }
  .feed li { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); padding: 10px 16px; }
  .feed time { grid-column: 1 / -1; }
  .feed li > :last-child { grid-column: 2; }
}
@media (max-width: 560px) {
  .attention li { flex-direction: column; align-items: flex-start; gap: 4px; padding: 12px 16px; }
  dl.summary > div { grid-template-columns: minmax(0, 1fr) auto; }
  dl.summary dt { grid-column: 1 / -1; }
  .check-page { padding: 18px 16px; }
}
/* Styles of the audit admin pages, served after site.css (static.go). */

/* audit.html: the mockup's inline styles as classes */
.aud-actions { margin: 0; justify-content: flex-start; }
.aud-entries { margin-top: 16px; }
.aud-narrowed { margin-top: 12px; font-size: 14px; color: var(--muted); }
.aud-next { margin-top: 14px; }
.aud-why { font-size: 14px; overflow-wrap: anywhere; }
.aud-entries .entry-body dd.hash { font-size: 12.5px; }
.aud-problem { grid-column: 1 / -1; }

/* Above the entries: how many, and the CSV of the search */
.aud-results { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; margin-top: 16px; font-size: 14px; color: var(--muted); }
.aud-results form { margin: 0; }
.aud-results + .aud-entries { margin-top: 10px; }

/* The entries' lines. Below 900 px the columns narrow and Who and Target stay (site.css hides them there);
 * below 720 px each line stacks: the time and the result, then who, what and, under it, the target. */
@media (max-width: 900px) {
  .aud-entries .entry-line, .aud-entries .entries-head { grid-template-columns: 128px minmax(0, .8fr) minmax(0, 1.2fr) minmax(0, 1.2fr) 76px; gap: 10px; }
  .aud-entries .entry-line .who, .aud-entries .entry-line .target, .aud-entries .entries-head .who, .aud-entries .entries-head .target { display: block; }
}
@media (max-width: 720px) {
  .aud-entries .entries-head { display: none; }
  .aud-entries .entry-line { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: 'time result' 'who result' 'what what' 'target target'; gap: 0 12px; align-items: start; padding: 10px 16px; }
  .aud-entries .entry-line time { grid-area: time; font-size: 13px; }
  .aud-entries .entry-line .who { grid-area: who; font-weight: 650; }
  .aud-entries .entry-line .what { grid-area: what; }
  .aud-entries .entry-line .target { grid-area: target; color: var(--muted); }
  .aud-entries .entry-line .result { grid-area: result; }
  .aud-entries .entry-line > span { white-space: normal; overflow-wrap: anywhere; }
  .aud-entries .entry-body { padding: 12px 16px 16px; }
}
@media (max-width: 560px) {
  .aud-actions .btn { flex: 1; }
}
/* Styles of the catalogue admin pages (Boards and peripherals, a board, Signing keys and their check
 * pages), served after site.css (static.go). The card heads and the field errors are site.css's. */

/* A card with a head of its own (a heading, a line, its own button), then a table, a list or an empty state */
.cat-card + .cat-card { margin-top: 16px; }
.cat-card > .table-wrap, .cat-card > .empty, .cat-card > dl.summary { border-top: 1px solid var(--line); }
.cat-card > dl.summary { padding: 0 20px; }
/* A muted line under a card's list: why an action isn't offered (a board with releases has no Remove) */
.cat-card-note { padding: 10px 20px 14px; border-top: 1px solid var(--line); color: var(--muted); font-size: 14px; }
.cat-foot { margin-top: 12px; font-size: 14px; }

/* Compact tables: a name with its id under it */
.cat-table tbody th[scope='row'] small { display: block; color: var(--faint); font-size: 12.5px; font-weight: 400; }
.cat-table small.cat-id { font-family: var(--mono); color: var(--muted); }
.cat-digest { display: block; font-size: 13px; color: var(--muted); white-space: nowrap; }
.cat-digests { margin-top: 4px; font-size: 13px; }
.cat-digests > summary { color: var(--accent); font-weight: 600; cursor: pointer; }
.cat-digests dl.kv { margin-top: 6px; font-size: 13px; }

/* The board form: chip revision rows; a field with a problem also gets a red bar on its left, since its
 * error sits inside the label or legend (catalogue-errors) */
.cat-cr { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr); }
.cat-cr .field { margin-bottom: 8px; }
.cat-form fieldset.field + fieldset.field { margin-top: 14px; }
/* Fields side by side start at the top: their hints sit under the field, so a long one or an error in a
 * neighbour doesn't push this one's field away from its label */
.cat-form .field-row > .field { align-content: start; }
.field.cat-invalid { padding-left: 12px; border-left: 3px solid var(--red); }

/* Check pages: the summary list of what the action is about, then what changes */
.check-page dl.summary { margin-bottom: 18px; }
.check-page .cat-more { margin-top: 12px; font-size: 14px; }

@media (max-width: 560px) {
  .cat-cr { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .cat-cr > .field:first-child { grid-column: 1 / -1; }
  .cat-card > dl.summary, .cat-card-note { padding-left: 16px; padding-right: 16px; }
}
/* Styles of the Flasher admin pages, served after site.css (static.go). The tabs Programs and Board
 * descriptions, the card heads and the field errors are site.css's. */

.fl-panel { padding-top: 20px; }

/* A card with a head and a body */
.fl-card + .fl-card, .fl-two + .fl-card, .fl-card + .fl-two { margin-top: 16px; }
.fl-card-body { padding: 0 20px 12px; }
.fl-card > .fl-card-body:first-child { padding-top: 8px; }
.fl-offer { padding: 4px 0 6px; font-size: 15px; }
.fl-offer + .fl-offer { border-top: 1px solid var(--line); padding-top: 10px; }

/* A build's row, when the audit log or a done notice links it: a steady tint, never a flash */
.fl-list tbody tr:target > * { background: var(--accent-bg); }

/* A board descriptions file's boards and what changed */
.fl-two { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; align-items: start; }
.fl-boards { margin: 0; padding: 0 20px 14px; list-style: none; font-size: 14.5px; }
.fl-boards li, .fl-change li { padding: 6px 0; border-top: 1px solid var(--line); overflow-wrap: anywhere; }
.fl-boards li:first-child, .fl-change li:first-child { border-top: 0; }
.fl-name { color: var(--muted); }
.fl-change { margin: 0; padding: 0 20px 14px; font-size: 14.5px; }
.fl-change > div + div { margin-top: 10px; }
.fl-change dt { font-weight: 650; }
.fl-change dd { margin: 2px 0 0; }
.fl-change ul { margin: 0; padding: 0; list-style: none; }

/* The check pages */
.check-page .fl-note { margin-top: 12px; color: var(--muted); font-size: 14.5px; }
.check-page .fl-facts { margin-top: 16px; }
.check-page .fl-confirm { margin: 18px 0 0; }
.check-page .fl-confirm .check { margin: 0; font-weight: 600; }

/* Upload forms */
.fl-upload { max-width: 760px; }
.fl-upload .field-row > .field { align-content: start; }
.fl-upload input[type='file'] { height: auto; padding: 8px 10px; }

@media (max-width: 720px) {
  .fl-card-body, .fl-boards, .fl-change { padding-left: 16px; padding-right: 16px; }
}
/* Styles of the Overview, the admin home, served after site.css (static.go). The card heads, the attention
 * list and the activity feed are site.css's. */

.ov-card + .ov-card { margin-top: 16px; }
.ov-card > .table-wrap, .ov-card > .attention, .ov-card > .feed, .ov-card > .empty { border-top: 1px solid var(--line); }

/* What panels get now: a row per board, a column per channel, the channels sharing the width evenly */
.ov-grid { table-layout: fixed; }
.ov-grid thead th:first-child { width: 22%; }
.ov-grid th, .ov-grid td { padding-left: 14px; padding-right: 14px; }
.ov-grid tbody th[scope='row'] { min-width: 170px; overflow-wrap: anywhere; }
.ov-grid td { vertical-align: top; }
.ov-grid td small { margin-top: 2px; }
.ov-grid td small.ov-warn { color: var(--amber); }
.ov-version { font-weight: 650; white-space: nowrap; }

/* Under the recent activity: the audit log */
.ov-more { padding: 12px 20px 16px; border-top: 1px solid var(--line); font-size: 14px; }

@media (max-width: 720px) {
  .ov-grid th, .ov-grid td { padding-left: 0; padding-right: 0; }
  .ov-grid tbody th[scope='row'] { min-width: 0; }
  .ov-more { padding-left: 16px; padding-right: 16px; }
}
/* Styles of the profile admin pages, served after site.css (static.go). The tabs, the card heads and the
 * field errors are site.css's. */

/* The tabs' part */
.pro-panel { padding-top: 20px; }
.pro-panel > .card + .card { margin-top: 16px; }
.pro-panel .field-row > .field { align-content: start; }

/* A page of one question, under its page head: a check page (site.css) */
.pro-dialog { max-width: 640px; }
.pro-dialog p + .field, .pro-dialog p + fieldset, .pro-dialog p + .pro-confirm { margin-top: 14px; }
.pro-dialog .secret { margin: 8px 0 6px; }
.pro-dialog .codes { margin-top: 12px; }
.pro-dialog .setup-grid { margin-top: 6px; }
.pro-dialog .setup-grid .field { margin-top: 14px; }
.pro-dialog .setup-grid p + p { margin-top: 0; }

/* Second step and signed-in browsers: rows with their links, an ordinary card with one red button */
.pro-nostep { margin-bottom: 14px; }
.danger-row form, .section-foot form { margin: 0; }
.danger-row .row-links { flex: 0 1 auto; }

/* API tokens: the list, the new token's page and the secret shown once */
.pro-tokens .list tbody th[scope='row'] small { display: block; color: var(--faint); font-size: 12.5px; font-weight: 400; }
.row-links form { display: inline; margin: 0; }
.row-links .linkbutton { font-size: 14px; white-space: nowrap; }
.pro-form { max-width: 720px; }
.pro-secret .field { margin-top: 14px; }
.pro-secret .field input[readonly] { color: var(--ink); font: 14px var(--mono); }
.pro-secret h2 { margin: 20px 0 6px; font-size: 17px; }
.pro-secret pre.cmd + p { margin-top: 10px; }

/* API help (admin-help.html): a card per part, with its calls and curl examples */
.help-api > .card + .card { margin-top: 16px; }
.help-toc { max-width: none; }
.help-toc h2 { margin-bottom: 8px; font-size: 15px; }
.help-toc ol { margin: 0; padding-left: 22px; columns: 2 240px; column-gap: 32px; font-size: 14.5px; }
.help-api .prose ol > li + li { margin-top: 10px; }
.help-api .prose pre code { white-space: pre; }
.help-codes dt { white-space: nowrap; }

/* The authenticator's QR code, here and on the sign-in's enrol page: a white box in both themes, since a
 * scanner needs dark modules on a light ground; its quiet zone is drawn inside the SVG. */
svg.qr { width: 200px; height: 200px; padding: 0; border-radius: 4px; }
.auth svg.qr { margin: 2px auto 6px; }

@media (max-width: 560px) {
  .help-codes { grid-template-columns: minmax(0, 1fr); }
  .help-codes dd { margin-bottom: 6px; }
}
/* Styles of the Releases pages (templates/admin-releases.html and admin-releases-check.html), served after
   site.css (static.go). The page head, lifecycle strip, tabs, card heads, row groups, field errors, choice
   cards, check page, summary list, short hashes, filter chips and the board picker are site.css's. */

/* The list: the board chips beside the state chips, and the board under a version */
.rel-filter-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0 18px; }
.rel-boards { padding-right: 18px; border-right: 1px solid var(--line); }
.rel-list tbody th small, .rel-panel .list tbody th small { display: block; margin-top: 2px; color: var(--faint); font-size: 12.5px; font-weight: 500; }
.rel-list .tags { gap: 4px 6px; }

/* Under the lifecycle strip: a step it reached and then moved back from, and since when it is on alpha or beta */
.lifecycle li.left { border-top-color: var(--line-strong); }
.lifecycle li.left b { color: var(--muted); font-weight: 600; }
.lifecycle + .rel-since { margin: -8px 0 18px; color: var(--muted); font-size: 14px; }

/* A release's tabs (site.css's), then the tab's part */
.rel-panel { padding-top: 20px; }
.rel-panel > * + * { margin-top: 16px; }

/* Files: one table grouped by kind (a tbody each, headed by its rowgroup), the upload's results, and the
   upload form */
.card-head p.rel-gap { color: var(--amber); }
.rel-results th.mono { overflow-wrap: anywhere; }
.rel-add > summary { padding: 16px 22px; font-weight: 650; cursor: pointer; }
.rel-add-body { padding: 0 22px 20px; }
.rel-upload .dropzone input { max-width: 100%; margin-top: 6px; font: 14px var(--font); color: var(--ink); }
.rel-upload .dropzone label { cursor: pointer; }
.rel-kinds { margin: 12px 0 0; padding: 0; list-style: none; font-size: 14px; color: var(--muted); }
.rel-kinds li + li { margin-top: 4px; }
.rel-kinds b { display: inline-block; min-width: 92px; color: var(--ink); font: 600 13px var(--mono); }
.rel-rules { margin-top: 14px; }
.rel-rules > summary { cursor: pointer; font-size: 14.5px; font-weight: 600; }
.rel-rules .field-row { margin-top: 12px; }
.rel-rules > .hint { color: var(--muted); font-size: 13px; }

/* Notes and settings */
.rel-notes { font-size: 15px; }
.rel-settings-title { margin: 6px 0 12px; }
.rel-path { margin: 0 0 4px; }
.rel-optional { margin-top: 4px; }
.rel-optional > summary { margin-bottom: 14px; cursor: pointer; font-size: 14.5px; font-weight: 600; }
.rel-form { max-width: 720px; }
.rel-path-name { margin-bottom: 14px; font-size: 13px; color: var(--muted); overflow-wrap: anywhere; }

/* History: refused attempts folded away */
.rel-refused { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.rel-refused > summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--muted); }
.rel-refused .timeline { margin-top: 8px; }

/* Check pages: the channel choice (site.css's choice cards), What changes, boot parts, the typed version */
.rel-check-h { margin-top: 20px; font-size: 16px; }
.rel-check > h2:first-child { margin-top: 0; }
.rel-changes { margin-top: 10px; border: 1px solid var(--line); border-radius: 8px; }
.rel-changes caption { padding: 0 0 6px; text-align: left; font-size: 14px; font-weight: 650; }
.rel-changes th, .rel-changes td, .rel-changes tbody th[scope='row'] { padding: 9px 14px; }
.rel-changes td small { display: block; color: var(--muted); font-size: 12.5px; }
.rel-changes td small.rel-warn { color: var(--amber); }
.rel-changes tr.rel-same th[scope='row'] { color: var(--muted); font-weight: 600; }
.rel-check > .table-wrap + p { margin-top: 14px; }
.rel-parts { margin: 16px 0 0; padding: 0; border: 0; }
.rel-parts legend { margin-bottom: 8px; font-weight: 650; }
.rel-part { padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; }
.rel-part + .rel-part { margin-top: 8px; }
.rel-sha { display: block; margin: 4px 0 2px; }
.rel-confirm { max-width: 320px; margin: 18px 0 0; }

/* A voice pack's listen page: a table of clips per category */
.section + .rel-voice { margin-top: 16px; }
.rel-voice-title { margin-bottom: 8px; }
.rel-voice > .rel-voice-group, .rel-voice > .empty { border-top: 1px solid var(--line); }
.rel-voice-group h3 { margin: 0; padding: 14px 20px 4px; font-size: 15px; }
.rel-clips tbody th[scope='row'] { min-width: 150px; }
.rel-clips th small { display: block; color: var(--faint); font: 12.5px/1.5 var(--mono); overflow-wrap: anywhere; font-weight: 400; }
.rel-clip-id { font: 13px/1.5 var(--mono); }
.rel-clips audio { display: block; width: 260px; max-width: 100%; height: 36px; }
.rel-clips td.rel-clip-file { width: 1%; white-space: nowrap; font-size: 14px; }
.rel-voice-problem { color: var(--amber); }

@media (max-width: 720px) {
  .rel-changes caption { display: block; padding: 10px 14px 8px; border-bottom: 1px solid var(--line); }
  .rel-changes tr { padding: 10px 14px; }
  .rel-changes th, .rel-changes td, .rel-changes tbody th[scope='row'] { display: block; padding: 3px 0; }
  .rel-voice-group h3 { padding-left: 16px; padding-right: 16px; }
  .rel-clips tbody th[scope='row'] { min-width: 0; }
  .rel-clips audio { width: 100%; }
  .rel-clips td.rel-clip-file { width: auto; }
}

@media (max-width: 560px) {
  .rel-boards { padding-right: 0; border-right: 0; }
  .rel-add > summary { padding: 14px 16px; }
  .rel-add-body { padding: 0 16px 16px; }
  .rel-kinds b { display: block; }
}
/* Styles of the settings admin pages, served after site.css (static.go). The tabs and the field errors are
 * site.css's. */

/* The tabs are site.css's; under them, the tab's cards */
.set-panel { padding-top: 20px; }
.set-panel > .card + .card, .set-panel > form + .card { margin-top: 16px; }
.set-panel > .notice + .notice { margin-top: 10px; }
.set-panel > .notice + .card { margin-top: 16px; }
.set-panel .section > .muted { margin: 0; }
.set-panel .section .footnote { margin-top: 12px; }
#email-test { display: none; }
/* The Email card's one status line: whether email works */
.set-status { display: flex; align-items: baseline; gap: 10px; margin: 0 0 18px; padding: 10px 14px; border-radius: 8px; background: var(--soft); font-size: 14.5px; }
.set-status.good { background: var(--accent-bg); }
.set-status.warn { background: var(--amber-bg); }
.set-status.bad { background: var(--red-bg); }
.set-mark { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--faint); transform: translateY(-1px); }
.set-status.good .set-mark { background: var(--accent); }
.set-status.warn .set-mark { background: var(--amber); }
.set-status.bad .set-mark { background: var(--red); }
/* Fields side by side start level, whatever hints they carry */
.set-panel .field-row > .field { align-content: start; }
/* Styles of the stats admin pages, served after site.css (static.go). */

/* The chart colours (FWS-068), checked with the dataviz palette validator against the card surface in
 * both themes: --s1, --s2 and --s3 pass every pair for colour-blind and normal vision; the gray of
 * "the rest" (older versions, checks not counted) passes with them but is below 3:1 against the card,
 * which each chart's table view relieves. Single-series marks use --s1. */
:root { --st-rest: #b0bec1; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) { --st-rest: #4a5a5f; }
}
:root[data-theme='dark'] { --st-rest: #4a5a5f; }

.stats .chart .line { stroke: var(--s1); }
.stats .chart .area-fill { fill: var(--s1); opacity: .1; }
.stats .chart .end { fill: var(--s1); stroke: var(--surface); stroke-width: 2; }
.stats .chart .st-pt { fill: var(--s1); }
.stats .chart .st-today { fill: var(--surface); stroke: var(--s1); stroke-width: 2; }
.stats .chart .st-rest { fill: var(--st-rest); }
.stats .chart .st-sofar { opacity: .55; }
/* A surface halo keeps the marks' labels readable where a grid line or the data line passes. */
.stats .chart text.st-mark, .stats .chart text.end-label { paint-order: stroke; stroke: var(--surface); stroke-width: 4px; stroke-linejoin: round; }
.stats .legend i.s1 { background: var(--s1); }
.stats .legend i.s2 { background: var(--s2); }
.stats .legend i.s3 { background: var(--s3); }
.stats .legend i.st-rest { background: var(--st-rest); }
.stats .st-key { display: inline-block; width: 9px; height: 9px; margin-right: 6px; border: 2px solid var(--s1); border-radius: 50%; vertical-align: -1px; }

/* stats.html: the mockup's inline styles as classes */
.stats .st-seg { margin: -6px 0 16px; } /* under the page head: the period of every chart below */
.stats .st-grid { margin-top: 16px; }
.stats .st-flag { margin-top: 10px; }
.stats .st-inline { display: inline; }

/* The board choice of the versions chart, and the board's share on its newest stable under it */
.stats .st-boards { margin: 0 0 12px; }
.stats .st-share { display: inline-block; min-width: min(100%, 220px); margin: 0 0 14px; padding: 10px 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--soft); }

/* Horizontal bars: HTML words, an SVG bar sized by its attributes (no style attribute) */
.st-bars { display: grid; gap: 8px; font-size: 13.5px; }
.st-bars > div { display: grid; grid-template-columns: minmax(90px, 1fr) minmax(0, 2fr) 44px; gap: 10px; align-items: center; }
.st-bars > div > span:last-child { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); }
.stats .chart svg.st-bar { display: block; width: 100%; height: 10px; overflow: visible; }
.st-bar .s1 { fill: var(--s1); }
.st-bar .st-rest { fill: var(--st-rest); }

/* Days left out */
.stats .st-days { margin-top: 16px; }
.stats .st-days .list { margin-bottom: 14px; }
.stats .st-leave { display: flex; flex-wrap: wrap; align-items: end; gap: 10px 14px; margin-top: 14px; }
.stats .st-leave .field { margin: 0; }
.stats .st-leave input[type='date'] { width: auto; }
/* Styles of the users admin pages, served after site.css (static.go). The field errors, the reset's choice
 * cards and the activity feed are site.css's. */

/* The list: the user's cell is the row's header, a name that links to the user's page */
.usr-list tbody th[scope='row'] { font-weight: 400; vertical-align: middle; }
.usr-list .person b a { color: var(--ink); }

/* The user's page: a summary value may hold several lines, each with a tag and a note */
.usr-line { display: block; }
.usr-line + .usr-line { margin-top: 6px; }
.usr-line small { display: block; color: var(--muted); font-size: 13px; }
.usr-note { margin-top: 12px; font-size: 13.5px; color: var(--muted); }
.usr-none { color: var(--muted); font-size: 14.5px; }

/* Under the recent activity: the audit log's links */
.usr-more { display: flex; flex-wrap: wrap; gap: 4px 18px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); font-size: 14px; }

/* Forms and check pages */
.usr-form { max-width: 720px; }
.usr-choices { margin-bottom: 4px; }
.check-page .usr-choices + .check-list, .check-page .check-list + .pro-confirm, .check-page .usr-note + .pro-confirm,
.check-page .check-list + .usr-note { margin-top: 14px; }
.check-page .pro-confirm { margin-bottom: 0; }
.usr-linkbox { margin: 12px 0; }
