/* re-psn project site. Hand-written; site/index.html is generated by tools/site.py.
   Colours are the dark tokens of docs/art/palette.json (python3 tools/site.py --check compares them). The palette follows the
   undecuple page (https://undecuple.github.io/me/), whose stylesheet credits it to guts.nvim; the border grey is one step
   lighter there than here (#787487, not #554a62) so that frames reach the 3:1 contrast tools/test_site.py asks for.
   There is one theme, dark. Every palette slot has a job (see the roles below). tools/test_site.py computes the contrast of every
   text colour on its background from palette.json: 4.5:1 or more. No fonts or images are loaded from anywhere. */

/* palette:dark */
:root {
  color-scheme: dark;
  --bg0: #101113;
  --bg1: #161719;
  --bg2: #161719;
  --bg3: #2b2733;
  --bg4: #2b2733;
  --bg5: #554a62;
  --fg0: #9f9e99;
  --fg1: #e1ffe5;
  --grey0: #554a62;
  --grey1: #787487;
  --grey2: #7a837c;
  --red: #ac7f7b;
  --orange: #997e95;
  --yellow: #997e95;
  --green: #a7d8b0;
  --aqua: #a7d8b0;
  --blue: #8288a0;
  --purple: #997e95;
}
/* /palette */

/* Roles that do not change with the mode. Slot jobs: bg0 page, bg1 panel (code, pre, chips, table heads), bg2 raised bars (title,
   key bar, switch), bg3 hover, bg4 selected row and table rules, bg5 code border and scrollbar; grey0 dotted separators, grey1 frames;
   grey2 muted text (dark); fg0 text; fg1 strong text; the seven accents are in the text roles below and in borders. */
:root {
  --page: var(--bg0);
  --panel: var(--bg1);
  --raised: var(--bg2);
  --hover: var(--bg3);
  --select: var(--bg4);
  --thumb: var(--bg5);
  --faint: var(--grey0);
  --line: var(--grey1);
  --t-ok: var(--green);
  --t-warn: var(--yellow);
  --t-unv: var(--orange);
  --t-info: var(--aqua);
  --t-plan: var(--blue);
  --t-dim: var(--purple);
  --t-bad: var(--red);
}

/* Text roles. tools/test_site.py checks that every pair of text role and background is at least 4.5:1. */
/* roles:dark */
:root {
  --text: var(--fg0); --strong: var(--fg1); --muted: var(--grey2); --link: var(--blue);
  --c-h1: var(--fg1); --c-h2: var(--blue); --c-h3: var(--fg1); --c-cmd: var(--fg1); --c-prompt: var(--fg1);
  --c-code: var(--purple); --c-id: var(--aqua); --c-err: var(--red); --c-key: var(--fg1);
  --tt-ok: var(--green); --tt-warn: var(--purple); --tt-unv: var(--purple); --tt-info: var(--aqua);
  --tt-plan: var(--blue); --tt-dim: var(--purple); --tt-bad: var(--red); --tag-w: 1px;
  --c-num: var(--purple); --c-opt: var(--blue); --c-env: var(--fg1); --c-label: var(--green); --syn-w: normal;
}
/* /roles */

* { box-sizing: border-box; }

html {
  background: var(--page);
  color: var(--text);
  /* The same font list as the undecuple page, so the two sites look alike on one machine (local fonts only; nothing is loaded). */
  font-family: "Perfect DOS VGA 437", "Px437 IBM VGA 8x16", ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace;
  font-variant-ligatures: none;
  font-size: 16px;
  line-height: 1.5;
  -webkit-text-size-adjust: 100%;
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0 auto;
  max-width: 100ch;
  padding: 0 16px 32px;
  background: var(--page);
  color: var(--text);
  overflow-wrap: anywhere;
}

/* The banners (tools/site.py draws them with these classes): the wide one under the skip link, and a tall one at the left edge that
   replaces it on wide screens, where there is room beside the content. */
.banner { display: block; width: 100%; max-width: 660px; height: auto; margin: 16px auto 0; }
.banner-side { display: none; }
.bn-frame { fill: none; stroke: var(--line); stroke-width: 2; }
.bn-name { fill: var(--strong); }
@media (min-width: 1400px) {
  .banner { display: none; }
  .banner-side { display: block; position: fixed; left: 24px; top: 16px; width: 90px; height: auto; }
}

a { color: var(--link); text-decoration: underline; text-underline-offset: 0.2em; }
a:hover { color: var(--strong); }
::selection { background: var(--select); color: var(--strong); }
html { scrollbar-color: var(--thumb) var(--panel); }
a:focus-visible, summary:focus-visible {
  outline: 2px solid var(--strong);
  outline-offset: 2px;
}

.skip {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--panel);
  color: var(--strong);
  padding: 0.25em 1ch;
  border: 1px solid var(--yellow);
}
.skip:focus { left: 16px; top: 8px; z-index: 2; }

code, pre { font-family: inherit; font-size: 1em; }
code { background: var(--panel); color: var(--c-code); padding: 0 0.5ch; border-bottom: 2px solid var(--purple); }
pre {
  margin: 0.75em 0;
  padding: 0.5em 1ch;
  background: var(--panel);
  border: 1px solid var(--thumb);
  border-left: 3px solid var(--aqua);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
pre code { background: none; padding: 0; border: 0; color: var(--text); }

h1, h2, h3, h4 { color: var(--strong); font-size: 1em; font-weight: bold; line-height: 1.5; margin: 0; }
h1 { color: var(--c-h1); }
p { margin: 0.75em 0; }
ul { margin: 0.5em 0; padding-left: 3ch; }
li { margin: 0.25em 0; }

/* The block under the banner and the section headings follow the undecuple page: double frames, a key and value box with dotted leaders,
   a box of links, and a heading with a block of four greys. Frames are CSS borders, so every character stays real text. */
.sr { position: absolute; left: -9999px; }
.top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 26rem); gap: 0 16px; margin: 16px 0 0; align-items: stretch; }
.nfo { display: grid; align-content: start; grid-template-columns: max-content 1fr; gap: 2px 16px; padding: 8px 12px; border: 3px double var(--line); background: var(--panel); }
.nfo .k { color: var(--muted); }
.nfo .k::after { content: " ........"; opacity: 0.5; }
.quick { border: 3px double var(--line); background: var(--panel); padding: 8px 12px; min-width: 0; }
.quick .qh { margin: 0 0 6px; color: var(--strong); letter-spacing: 0.14em; }
.quick ul { list-style: none; margin: 0; padding: 0; column-count: 2; column-gap: 2ch; }
.quick li { margin: 0; break-inside: avoid; }
.quick li::before { content: "> "; color: var(--muted); }
[id] { scroll-margin-top: 1rem; }

main { display: block; }

section { margin: 1.75em 0 0; }
section > h2 { display: flex; align-items: center; gap: 10px; margin: 0 0 0.5em; color: var(--strong); letter-spacing: 0.14em; text-transform: uppercase; }
section > h2::before {
  content: "";
  flex: none;
  width: 36px;
  height: 14px;
  background: linear-gradient(90deg, var(--fg0) 0 25%, var(--grey1) 25% 50%, var(--grey0) 50% 75%, var(--bg3) 75%);
}

section h3 { margin: 1.25em 0 0.25em; color: var(--c-h3); border-bottom: 1px solid var(--orange); }
section h3::before { content: "# "; color: var(--muted); }
section h4 { margin: 0.75em 0 0; color: var(--text); }
section > h2 + p, section > h2 + h3 { margin-top: 0; }
.count { color: var(--muted); font-weight: normal; }
.note { color: var(--muted); }
.notice { border-left: 3px solid var(--blue); padding-left: 1ch; }
.status-line { color: var(--muted); }

.docs { list-style: none; padding-left: 0; }
.docs li { margin: 0.5em 0; padding-bottom: 0.5em; border-bottom: 1px dotted var(--faint); }
.docs li:last-child { border-bottom: 0; }

/* Status tags: the word is always shown, in the tag's text colour; the border colour is a second cue, never the only one. */
.tag {
  display: inline-block;
  padding: 0 1ch;
  border: var(--tag-w) solid var(--line);
  background: var(--page);
  color: var(--text);
}
.tag::before { content: "["; }
.tag::after { content: "]"; }
.tag.ok { border-color: var(--t-ok); color: var(--tt-ok); }
.tag.warn { border-color: var(--t-warn); color: var(--tt-warn); }
.tag.unv { border-color: var(--t-unv); color: var(--tt-unv); }
.tag.info { border-color: var(--t-info); color: var(--tt-info); }
.tag.plan { border-color: var(--t-plan); color: var(--tt-plan); }
.tag.dim { border-color: var(--t-dim); color: var(--tt-dim); }
.tag.bad { border-color: var(--t-bad); color: var(--tt-bad); }

table { width: 100%; border-collapse: collapse; margin: 0.5em 0; border: 3px double var(--line); background: var(--panel); }
th, td { text-align: left; vertical-align: top; padding: 0.25em 1ch; }
thead th { color: var(--strong); font-weight: normal; border-bottom: 1px solid var(--line); }
tbody tr:nth-child(even) { background: var(--page); }
table.feat, table.set { table-layout: fixed; }
table.feat th:nth-child(2) { width: 22ch; }
table.feat th:nth-child(3) { width: 14ch; }
table.set th:nth-child(1) { width: 25ch; }
table.set th:nth-child(2) { width: 30ch; }
table.set th:nth-child(3) { width: 18ch; }

.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(28ch, 1fr)); gap: 0 3ch; }
.cols ul { padding-left: 2ch; }

footer { margin: 2em 0 0; color: var(--muted); border-top: 1px dotted var(--faint); }

/* Narrow screens: a table row becomes a block, each cell labelled, so nothing scrolls sideways. */
@media (max-width: 48rem) {
  table.feat, table.set { table-layout: auto; }
  table.stack, table.stack tbody, table.stack tr, table.stack td { display: block; width: 100%; }
  table.stack thead { position: absolute; left: -999px; }
  table.stack tr { border-top: 1px solid var(--faint); padding: 0.5em 0; }
  table.stack td { border: 0; padding: 0.1em 0; }
  table.stack td::before { content: attr(data-label) ": "; color: var(--muted); }
  table.stack td:first-child::before { content: ""; }
  .top { grid-template-columns: minmax(0, 1fr); gap: 8px 0; }
  .quick ul { column-count: 1; }
}

@media print {
  html { background: #fff; color: #000; }
  a { color: #000; }
}

/* Back to top: a plain link, fixed at the bottom right of the document view. */
body { padding-bottom: 72px; }
.totop {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 48px;
  min-height: 48px;
  padding: 0 1ch;
  background: var(--raised);
  color: var(--strong);
  border: 1px solid var(--line);
  border-bottom: 3px solid var(--yellow);
  text-decoration: none;
}
.totop:hover { background: var(--strong); color: var(--page); }
.totop:focus-visible { outline: 2px solid var(--strong); outline-offset: 2px; }

/* ---- The terminal interface (site/terminal.js adds .tui-on to the root and builds #tui) ---------------------------------- */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.tui, .plain-bar { display: none; }
html.tui-on:not(.plain) .tui { display: grid; }
html.tui-on:not(.plain) :is(.top, main, .skip, .totop) { display: none; }
html.tui-on.plain .plain-bar { display: block; margin: 16px 0 0; }
html.tui-on:not(.plain) footer { margin-top: 0.75em; }
html.tui-on:not(.plain) body { padding-bottom: 16px; }

.tui button { font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; text-align: left; cursor: pointer; }
.tui-plain, .tui .tui-plain { color: var(--strong); background: none; border: 1px solid var(--line); font: inherit; cursor: pointer; padding: 0 1.5ch; }
.tui-plain:hover, .tui .tui-plain:hover { background: var(--hover); }
.tui button:focus-visible, .tui-plain:focus-visible, .tui input:focus-visible, .tui-out:focus-visible {
  outline: 2px solid var(--strong);
  outline-offset: -2px;
}
.tui-plain:focus-visible { outline-offset: 2px; }

.tui {
  grid-template-rows: auto auto minmax(0, 1fr) auto auto auto;
  height: calc(100vh - 6.5rem);
  height: calc(100dvh - 6.5rem);
  min-height: 24rem;
  margin: 16px 0 0;
  border: 1px solid var(--line);
  background: var(--page);
}
.tui ul { list-style: none; margin: 0; padding: 0; }
.tui li { margin: 0; }
.tui-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 2ch; padding: 0.25em 1ch; background: var(--raised); color: var(--strong); border-top: 3px solid var(--yellow); border-bottom: 1px solid var(--line); }
.tui-name { font-weight: bold; color: var(--c-h1); }
.tui-ver { color: var(--muted); flex: 1; }
.tui ul.tui-fkeys { display: flex; flex-wrap: wrap; gap: 4px 1ch; padding: 0.25em 1ch; background: var(--raised); color: var(--c-key); border-bottom: 3px double var(--line); }
.tui .fk { color: var(--c-key); border: 1px solid var(--line); padding: 0 1ch; }
.tui .fk:hover { background: var(--hover); }
.tui-panes { display: grid; grid-template-columns: 24ch minmax(0, 1fr); min-height: 0; }
.tui-menu { border-right: 1px solid var(--line); scrollbar-color: var(--thumb) transparent; padding: 0.5em 0; overflow-y: auto; }
.tui-menu ul { padding: 0 1ch; }
.tui-menu li { padding: 0 0 4px; }
/* Each tab is an outlined box; the open one is marked by colour, a thicker left edge and the ">" mark, never by colour alone. */
.tui-menu .mi { display: block; width: 100%; padding: 0 1ch; border: 1px solid var(--line); }
.tui-menu .mi::before { content: "  "; white-space: pre; }
.tui-menu .mi:hover { text-decoration: underline; background: var(--hover); }
.tui-menu .mi[aria-current] { background: var(--select); color: var(--strong); border-color: var(--strong); box-shadow: inset 3px 0 var(--yellow); }
.tui-menu .mi[aria-current]::before { content: "> "; }
.tui-content { display: flex; flex-direction: column; min-height: 0; min-width: 0; }
.tui .chip.tui-back { display: none; }
.tui-out { flex: 1; overflow: auto; padding: 0.5em 1ch; min-height: 0; white-space: pre-wrap; overflow-wrap: anywhere; display: flex; flex-direction: column; }
.tui-out > * { flex: 0 0 auto; }
.tui-out .ln { min-height: 1.5em; }
.tui-out { scrollbar-color: var(--thumb) var(--panel); scrollbar-gutter: stable; }
.tui-out .ps { color: var(--c-prompt); font-weight: bold; }
.tui-out .echo { color: var(--c-cmd); }
.tui-out .strong { color: var(--strong); font-weight: bold; }
.tui-out .head { color: var(--c-h3); font-weight: bold; border-bottom: 1px solid var(--orange); }
.tui-out .cmd { color: var(--c-cmd); font-weight: bold; }
.tui-out .id { color: var(--c-id); border-bottom: 1px dotted var(--aqua); }
.tui-out .err { color: var(--c-err); font-weight: bold; border-left: 3px solid var(--red); padding-left: 1ch; }
.tui-out .code, .tui-out .flag { background: var(--panel); color: var(--c-code); padding: 0 0.5ch; border-bottom: 2px solid var(--purple); }

/* Each answer is a numbered file: a header with its name, a gutter of line numbers with a rule beside it, and a frame above and
   below that runs the width of the pane. The numbers are drawn from data-n, so they are never selected, copied or read. A line
   that wraps stays in its one grid row, so its further rows have an empty gutter. */
.tui-out .file { --gw: 4ch; --gp: 1ch; margin: 0.25em -1ch 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.tui-out .file.gw2 { --gw: 5ch; }
.tui-out .file.gw3 { --gw: 6ch; }
.tui-out .file.gw4 { --gw: 7ch; }
.tui-out :is(.file-head, .fl) { display: grid; grid-template-columns: var(--gw) minmax(0, 1fr); }
.tui-out .file-head { border-bottom: 1px solid var(--line); user-select: none; -webkit-user-select: none; }
.tui-out .fl { min-height: 1.5em; }
.tui-out .gut { border-right: 1px solid var(--line); padding-right: var(--gp); text-align: right; color: var(--muted); user-select: none; -webkit-user-select: none; }
.tui-out .gut::before { content: attr(data-n); }
.tui-out .tx { min-width: 0; padding-left: var(--gp); white-space: pre-wrap; overflow-wrap: anywhere; }
/* The newest answer fills what is left of the pane, and the gutter rule runs to the bottom of it, like a file open in a viewer. */
.tui-out .file-body { background: linear-gradient(var(--line), var(--line)) calc(var(--gw) - 1px) 0 / 1px 100% no-repeat; }
.tui-out .file:last-child { flex: 1 0 auto; display: flex; flex-direction: column; }
.tui-out .file:last-child .file-body { flex: 1; }
.tui-out .file-head .tx { padding-top: 0.4em; padding-bottom: 0.4em; }
.tui-out .file-label { color: var(--muted); }
.tui-out .file-name { color: var(--strong); font-weight: bold; }
.tui-out .num { color: var(--c-num); }
.tui-out .opt { color: var(--c-opt); font-weight: var(--syn-w); }
.tui-out .env { color: var(--c-env); font-weight: var(--syn-w); }
.tui-out .label { color: var(--c-label); font-weight: bold; }

.tui-cmd { position: relative; border-top: 1px solid var(--line); padding: 0.25em 1ch; }
.tui-hint { margin: 0; color: var(--muted); }
.tui:not(.empty) .tui-hint { visibility: hidden; }
.tui-row { position: relative; display: flex; align-items: center; gap: 1ch; }
.tui-ps { color: var(--c-prompt); font-weight: bold; }
.tui-field { position: relative; flex: 1; min-width: 0; display: flex; }
.tui-ghost { position: absolute; inset: 0; padding: 0.25em 0; overflow: hidden; white-space: pre; pointer-events: none; color: var(--muted); }
.tui-ghost-pad { visibility: hidden; }
.tui-row input {
  flex: 1;
  min-width: 0;
  font: inherit;
  color: var(--strong);
  background: transparent;
  border: 0;
  padding: 0.25em 0;
  caret-color: var(--strong);
  caret-shape: block;
}
/* Suggestions: a list above the prompt; the chosen item is marked like the chosen menu entry. */
.tui ul.tui-list { position: absolute; left: -1ch; right: -1ch; bottom: calc(100% + 0.25em); z-index: 2; max-height: 14em; overflow-y: auto; background: var(--panel); border: 1px solid var(--line); scrollbar-color: var(--thumb) var(--panel); }
.tui-list .ac-item { display: flex; flex-wrap: wrap; gap: 0 2ch; padding: 0 1ch; cursor: pointer; }
.tui-list .ac-item:hover { background: var(--hover); }
.tui-list .ac-item[aria-selected="true"] { background: var(--select); box-shadow: inset 3px 0 var(--yellow); }
.tui-list .ac-name { color: var(--c-cmd); font-weight: bold; }
.tui-list .ac-item:is([aria-selected="true"], :hover) :is(.ac-name, .ac-desc) { color: var(--strong); }
.tui-list .ac-desc { color: var(--muted); min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The resting cursor is a block after the prompt; once the input has focus the real caret takes over. */
.cursor { position: absolute; left: 3ch; color: var(--strong); pointer-events: none; animation: blink 1.1s steps(1) infinite; }
.tui:not(.empty) .cursor, .tui-row:focus-within .cursor { display: none; }
@keyframes blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .cursor { animation: none; } }

.tui ul.tui-chips { display: none; flex-wrap: wrap; gap: 8px; padding: 8px 1ch; border-top: 1px solid var(--line); }
.tui .chip {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 1.5ch;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--line);
}
.tui .chip:hover { background: var(--hover); }
.tui-keys { margin: 0; padding: 0.25em 1ch; background: var(--raised); color: var(--muted); border-top: 1px solid var(--line); }
.tui .tag { margin-right: 0; padding: 0 0.5ch; }
.tui .tag::before, .tui .tag::after { content: none; }

/* Under about 70 columns: the menu becomes a row of tabs you can scroll sideways, the content is always shown below it, and
   command chips stand in for the keyboard. The title bar puts the name and version on one line and the controls under them. */
@media (max-width: 44rem) {
  .tui { height: auto; min-height: calc(100dvh - 5rem); grid-template-rows: auto auto 1fr auto auto auto; }
  .tui-title { gap: 0.25em 1.5ch; }
  .tui-name { flex: 0 0 auto; }
  .tui-ver { flex: 1 1 auto; white-space: nowrap; }
  .tui-title .tui-plain { flex: 0 0 auto; min-height: 44px; display: inline-flex; align-items: center; }
  .tui-panes { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  .tui-menu { overflow-x: auto; overflow-y: hidden; white-space: nowrap; padding: 0; border-right: 0; border-bottom: 1px solid var(--line); }
  .tui-menu ul { display: flex; flex-direction: row; gap: 4px; padding: 4px; }
  .tui-menu li { flex: 0 0 auto; padding: 0; }
  .tui-menu .mi { flex: 0 0 auto; width: auto; min-height: 44px; display: flex; align-items: center; padding: 0 1.5ch; }
  .tui-menu .mi::before, .tui-menu .mi[aria-current]::before { content: none; }
  .tui-menu .mi[aria-current] { box-shadow: inset 0 -3px var(--yellow); }
  .tui .chip.tui-back { display: none; }
  .tui-list .ac-item { min-height: 44px; align-items: center; }
  .tui ul.tui-chips { display: flex; }
  .tui-keys, .tui ul.tui-fkeys { display: none; }
  .tui-out { overflow: visible; }
  .tui-out .file { --gw: 2.5ch; --gp: 0.5ch; }
  .tui-out .file.gw2 { --gw: 3.5ch; }
  .tui-out .file.gw3 { --gw: 4.5ch; }
  .tui-out .file.gw4 { --gw: 5.5ch; }
}

/* The "see it in action" page (tools/site_action.py): a static diagram and numbered steps per scenario. Colours as in the status tags;
   the word on each edge and in each step is the cue, the colour is a second one. */
.action-diagram { display: block; width: 100%; max-width: 660px; height: auto; margin: 1em 0; }
.action-diagram .node { fill: var(--bg1); stroke: var(--line); stroke-width: 2; }
.action-diagram .node-name { fill: var(--strong); }
.action-diagram .node-addr { fill: var(--muted); }
.action-diagram .edge { fill: none; stroke-width: 3; }
.action-diagram .e-tcp { stroke: var(--tt-ok); }
.action-diagram .e-direct { stroke: var(--tt-warn); stroke-dasharray: 2 6; stroke-linecap: round; }
.action-diagram .e-blocked { stroke: var(--tt-bad); stroke-dasharray: 10 8; }
.action-diagram .e-relay { stroke: var(--tt-plan); stroke-width: 5; }
.action-diagram .edge-label { fill: var(--text); font-size: 13px; }
/* Each legend entry is an outlined box, in the colour of the line it names (the word is always there; the colour is a second cue). */
.legend { line-height: 2.1; }
.legend .lg { display: inline-block; margin: 0 1ch 0 0; padding: 0 1ch; border: 1px solid var(--line); line-height: 1.5; }
.legend .lg-tcp { color: var(--tt-ok); border-color: var(--t-ok); }
.legend .lg-direct { color: var(--tt-warn); border-color: var(--t-warn); }
.legend .lg-blocked { color: var(--tt-bad); border-color: var(--t-bad); }
.legend .lg-relay { color: var(--tt-plan); border-color: var(--t-plan); }
.steps { padding-left: 3ch; }
.steps li { margin: 0.25em 0; }
.steps .who { color: var(--muted); }
.steps .msg { color: var(--c-id); }
.action-diagram .packet { stroke: var(--bg0); stroke-width: 2; }
.action-diagram .p-tcp { fill: var(--tt-ok); }
.action-diagram .p-udp, .action-diagram .p-direct { fill: var(--tt-warn); }
.action-diagram .p-relay { fill: var(--tt-plan); }
.action-diagram .p-lost { fill: var(--tt-bad); }
.action-diagram .packet-label { fill: var(--strong); font-size: 13px; }
.action-diagram .off { display: none; }
.action-controls { margin: 1em 0; }
.ctl-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5ch 1ch; margin: 0.5em 0; }
.ctl { font: inherit; color: var(--text); background: var(--bg1); border: 1px solid var(--line); padding: 0.1em 1ch; cursor: pointer; }
.ctl[aria-pressed="true"] { color: var(--strong); border-color: var(--strong); font-weight: bold; }
.ctl:disabled { cursor: default; }
.ctl:focus-visible, .jump:focus-visible { outline: 2px solid var(--strong); outline-offset: 2px; }
.ctl-speed { color: var(--text); }
.action-caption { min-height: 3em; color: var(--text); }
.action-hint { color: var(--muted); }
.steps .jump { font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: pointer; text-align: left; }
.steps li.now { border-left: 3px solid var(--strong); padding-left: 1ch; margin-left: -1ch; font-weight: bold; }
[hidden] { display: none !important; }

.discuss-load { font: inherit; color: var(--strong); background: none; border: 1px solid var(--line); padding: 0.25em 1.5ch; cursor: pointer; }
.discuss-load:hover { background: var(--hover); }
.discuss-load:focus-visible { outline: 2px solid var(--strong); outline-offset: 2px; }
.discuss-load:disabled { cursor: default; color: var(--muted); }
.giscus { margin-top: 1em; }

/* The way back from the pages that stand apart from the main page: outlined, like the other buttons. */
.pagenav { display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 0; }
.pagenav .pn { font: inherit; color: var(--strong); background: none; border: 1px solid var(--line); padding: 0 1.5ch; text-decoration: none; cursor: pointer; }
.pagenav .pn:hover { background: var(--hover); color: var(--strong); }
.pagenav .pn:focus-visible { outline: 2px solid var(--strong); outline-offset: 2px; }
