/*
 * One page, one stylesheet, with the tokens and scales of the benches beside it.
 * A machine-produced fact -- an address, an identity, a value -- is set in the
 * mono face.
 *
 * This file is downloaded by whoever opens the page, comments included.
 */

:root {
  --ink: #17191c;
  --ink-quiet: #4a4f57;
  --ink-faint: #767c86;
  --page: #f7f8fa;
  --card: #ffffff;
  --edge: #dfe3e8;
  --accent: #1a5fb4;
  --bad: #b3261e;
  --good: #1c7c48;
  --waiting: #8a5a00;
  /* The warning colour: a value that went down since the first reading, and a
     meter whose last reading failed. Orange, as asked, and dark enough to read
     on white. */
  --falls: #c05600;

  --text-caption: 0.75rem;
  --text-small: 0.85rem;
  --text-body: 0.95rem;
  --text-lead: 1.1rem;
  --text-title: 1.5rem;

  --control: 34px;

  --gap-xs: 4px;
  --gap-s: 8px;
  --gap-m: 12px;
  --gap-l: 20px;
  --gap-xl: 32px;

  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --font: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

body {
  margin: 0;
  padding: var(--gap-xl) var(--gap-l);
  background: var(--page);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--text-body);
  line-height: 1.5;
}

main, .masthead { max-width: 1200px; margin: 0 auto; }
.masthead h1 { font-size: var(--text-title); margin: 0 0 var(--gap-xs); font-weight: 600; }

/* The link to the manual, in the title's row. Hidden until the manual
   answers, so the rule that shows it must not undo `hidden`.

   It shares a box with the account, and the box centres them. As a sibling of
   the account it sat at the top of the row, a few pixels above the name and
   the buttons beside it. The size is the account's own. */
.corner { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: var(--gap-s) var(--gap-m); }
.manual { white-space: nowrap; font-size: var(--text-small); }
.manual[hidden] { display: none; }
.manual { color: var(--accent); text-decoration: none; }
.manual:hover { text-decoration: underline; }
.lede { margin: 0 0 var(--gap-l); color: var(--ink-quiet); max-width: 70ch; }
.row.top { align-items: flex-start; }

.who { display: flex; gap: var(--gap-m); align-items: center; font-size: var(--text-small); }
.badge {
  font-size: var(--text-caption);
  color: var(--ink-quiet);
  border: 1px solid var(--edge);
  border-radius: 999px;
  padding: 0 var(--gap-s);
}

.panel {
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
  padding: var(--gap-l);
  margin-bottom: var(--gap-l);
}
.narrow-card { max-width: 24rem; margin-left: auto; margin-right: auto; }
body:not(.signed-in) .masthead { max-width: 24rem; }

.heading { font-size: var(--text-lead); font-weight: 600; margin: var(--gap-xl) 0 var(--gap-m); }
.panel .heading { margin-top: 0; }
.note { color: var(--ink-quiet); margin: 0 0 var(--gap-m); }
/* The reason somebody gave for asking for an account: their own lines, kept,
   and a long word that cannot push the table wider than the page. */
.rows td.reason { white-space: pre-wrap; overflow-wrap: anywhere; min-width: 12rem; max-width: 32em; }
/* The role a request is approved as, chosen in its own row: wide enough to
   read the longest of them. */
.rows td.choice { min-width: 10rem; }
/* The requests are followed by a panel, which would otherwise touch them. */
.requests { margin-bottom: var(--gap-l); }

.field { display: block; margin-bottom: var(--gap-m); }
.label { display: block; font-size: var(--text-small); color: var(--ink-quiet); margin-bottom: var(--gap-xs); }
.hint { color: var(--ink-faint); font-weight: 400; }

input[type=text], input[type=password], input[type=email], input[type=number], select {
  width: 100%;
  font-family: var(--font-mono);
  font-size: var(--text-small);
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 6px;
  padding: var(--gap-s) var(--gap-m);
  height: var(--control);
}
select { font-family: var(--font); cursor: pointer; }
input:focus-visible, select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}
/* A field the form fills itself and nobody may type in, such as the address of
   a converter chosen from the list. It stays where it is, so the row around it
   does not move, and it is grey so that it is plainly not for typing. */
input:disabled {
  background: var(--page);
  color: var(--ink-faint);
  cursor: default;
  -webkit-text-fill-color: var(--ink-faint);
  opacity: 1;
}

.row { display: flex; gap: var(--gap-m); align-items: flex-end; flex-wrap: wrap; }
.row .field { margin-bottom: 0; }
/* A field in a row has no margin of its own, so two rows of fields one under
   the other would touch. */
.row + .row { margin-top: var(--gap-m); }
/* Two fields that belong together, such as an address and its port: they take
   one line between them, and they wrap to the next line together. */
.row .pair { flex: 1 1 22rem; flex-wrap: nowrap; }
.narrow { width: 11rem; }
.minutes { width: 15rem; }
.grow { flex: 1 1 240px; }
/* The last button of a row, opposite the others. */
.row .end { margin-left: auto; }

button {
  font: inherit;
  font-size: var(--text-small);
  padding: 0 var(--gap-l);
  height: var(--control);
  border: 1px solid transparent;
  border-radius: 6px;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
}
button:hover { filter: brightness(1.08); }
button[disabled] { opacity: 0.6; cursor: default; }
button.quiet { background: var(--card); color: var(--accent); border-color: var(--edge); }
button.quiet:hover { filter: none; border-color: var(--accent); }
/* A header toggle that is on, such as Notify me. */
button.quiet.is-on { background: var(--accent); color: #fff; border-color: var(--accent); }
button.danger { background: var(--bad); }
button.small { height: 28px; padding: 0 var(--gap-m); }
/* A button whose whole label is a drawing, such as the trash can. Square, and
   the drawing takes the button's own colour, so it works on any of them. */
/* The one listed meter to read, beside its label rather than across the form. */
.choices.narrow-select { display: inline-block; width: auto; min-width: 16rem; max-width: 100%; }

/* The converters somebody was given, and which meters of each, under its row. */
td.give {
  display: flex;
  flex-direction: column;
  gap: var(--gap-s);
  align-items: flex-start;
}

/* The converter's name, and its meters on the line under it, so the two levels
   read as two levels rather than as one row of boxes. */
.give-converter {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs);
}

/* The meters of one converter, indented under its name so the two levels read
   as two levels. */
.give-converter .meters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-m);
  padding-left: var(--gap-l);
}

.small-choice { font-size: var(--text-small); }

button.icon { padding: 0 var(--gap-m); }
button.icon svg {
  width: 17px;
  height: 17px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
button.wide { width: 100%; }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* A button that opens a short list of links under it, such as Export. */
.menu { position: relative; }
.menu summary {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-s);
  font-size: var(--text-small);
  padding: 0 var(--gap-l);
  height: var(--control);
  border: 1px solid var(--edge);
  border-radius: 6px;
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.menu summary::-webkit-details-marker { display: none; }
.menu summary:hover, .menu[open] summary { border-color: var(--accent); }
.menu summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.menu .caret { font-size: var(--text-caption); }
.menu-items {
  position: absolute;
  right: 0;
  top: calc(100% + var(--gap-xs));
  z-index: 10;
  min-width: 18rem;
  display: flex;
  flex-direction: column;
  padding: var(--gap-xs) 0;
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
}
.menu-items a {
  display: flex;
  flex-direction: column;
  padding: var(--gap-s) var(--gap-m);
  color: var(--ink);
  text-decoration: none;
  font-size: var(--text-small);
}
.menu-items a .hint { font-size: var(--text-caption); }
.menu-items a:hover, .menu-items a:focus-visible { background: var(--page); outline: none; }

textarea {
  width: 100%;
  font-family: var(--font-mono);
  font-size: var(--text-small);
  border: 1px solid var(--edge);
  border-radius: 6px;
  padding: var(--gap-s) var(--gap-m);
}

/* Where the meters come from: three choices in a line, under the form. */
.source { margin: var(--gap-m) 0; align-items: center; gap: var(--gap-l); }
.source .label { margin: 0; }
.choice { font-size: var(--text-small); display: inline-flex; gap: var(--gap-xs); align-items: center; cursor: pointer; }

.privacy { margin: var(--gap-m) 0 0; font-size: var(--text-caption); color: var(--ink-faint); max-width: 80ch; }

/* A window: a form somebody opens, fills and closes, over the page it belongs
   to. The gateway bench's windows are the same shape.

   A row carries no margin of its own, so in a window whose fields sit in rows
   the rows would touch and the buttons would stand against the last field. The
   buttons stand further away than a row does, because they are not one more
   field. */
.window {
  border: 1px solid var(--edge);
  border-radius: 8px;
  padding: var(--gap-l);
  width: min(36rem, calc(100vw - 2 * var(--gap-l)));
  color: var(--ink);
  background: var(--card);
}
.window::backdrop { background: rgba(23, 25, 28, 0.35); }
.window h2 { font-size: var(--text-lead); margin: 0 0 var(--gap-s); }
.window .row { margin-top: var(--gap-m); }
.window .row.actions { margin-top: var(--gap-l); }
.window .refusal { margin-bottom: 0; }

/* The button over a table that opens the window to add a row to it. It needs
   the space below, or it touches the table it is about. */
.adds { margin-bottom: var(--gap-m); }
/* The row holding a panel's one action, under everything it acts on. */
.row.start { margin-top: var(--gap-l); }
.empty { color: var(--ink-faint); font-size: var(--text-small); margin: var(--gap-m) 0 0; }

.refusal, .notice {
  background: var(--card);
  border: 1px solid var(--bad);
  border-left-width: 4px;
  border-radius: 6px;
  padding: var(--gap-m) var(--gap-l);
  margin: var(--gap-m) 0 var(--gap-l);
  color: var(--bad);
}
.notice { border-color: var(--edge); border-left-color: var(--accent); color: var(--ink-quiet); }

.tabs { display: flex; gap: var(--gap-xs); margin-bottom: var(--gap-l); border-bottom: 1px solid var(--edge); }
.tab {
  background: none;
  color: var(--ink-quiet);
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  padding: 0 var(--gap-m);
}
.tab:hover { filter: none; color: var(--accent); }
.tab.is-active { color: var(--ink); border-bottom-color: var(--accent); font-weight: 600; }

.invited { margin-top: var(--gap-l); }

/* ------------------------------------------------------------------ tables */

.sheet {
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
  overflow-x: auto;
}
.rows { width: 100%; border-collapse: collapse; font-size: var(--text-small); }
.rows th, .rows td {
  text-align: left;
  padding: var(--gap-s) var(--gap-m);
  border-bottom: 1px solid var(--edge);
  white-space: nowrap;
}
.rows th {
  font-size: var(--text-caption);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  font-weight: 600;
}
.rows tbody tr:last-child td { border-bottom: none; }
.rows .mono { font-family: var(--font-mono); }
.rows .num { text-align: right; }
.rows .action { text-align: right; width: 1%; white-space: nowrap; }
/* The buttons of one row stand apart. They are appended by the script, so
   there is no whitespace between them to do it, and Change and Delete touched
   (reported 2026-09-20). */
.rows .action button + button { margin-left: var(--gap-s); }
.rows tr.is-disabled td { color: var(--ink-faint); }
#sessions tbody tr { cursor: pointer; }
#sessions tbody tr:hover { background: var(--page); }

.state-word.is-searching, .state-word.is-connecting { color: var(--waiting); }
.state-word.is-reading { color: var(--good); }
.state-word.is-ended { color: var(--ink-faint); }

/* ------------------------------------------------------------- one session */

.detail-head { align-items: center; margin-bottom: var(--gap-l); }
.detail-head h2 { font-family: var(--font-mono); font-size: var(--text-lead); margin: 0; }

.summary {
  display: flex;
  gap: var(--gap-xl);
  flex-wrap: wrap;
  margin-bottom: var(--gap-l);
  padding: var(--gap-m) var(--gap-l);
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
}
.fact { display: flex; flex-direction: column; }
.fact .name { font-size: var(--text-caption); color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0.04em; }
.fact .value { font-family: var(--font-mono); font-size: var(--text-lead); }

/* A meter's own row: its identity, then what is known about it, across the
   whole table. */
.readings tr.device td {
  background: var(--page);
  white-space: normal;
  padding-top: var(--gap-m);
}
.readings .identity { font-weight: 600; margin-right: var(--gap-m); }
.readings .facts { color: var(--ink-quiet); }
/* A meter whose last reading failed, before it has failed three in a row. The
   page's orange is its warning colour, as it is for a counter that went down. */
.readings .flag.is-warn { color: var(--falls); border-color: var(--falls); }
/* At the far end of the meter's own row, away from what is read. */
.readings tr.device td { position: relative; }
.readings .actions { float: right; display: inline-flex; gap: var(--gap-xs); margin: calc(-1 * var(--gap-xs)) 0; }

/* Mute and Solo: a toggle that is on is filled, as a pressed key. */
.readings .toggle.is-on { background: var(--accent); color: #fff; border-color: var(--accent); }

/* A meter the rounds do not read, and its values: kept, and faded. */
.readings tr.is-skipped td { color: var(--ink-faint); }
.readings tr.is-skipped .rises, .readings tr.is-skipped .falls { opacity: 0.5; }
.readings .flag.is-bad { color: var(--bad); border-color: var(--bad); }
.readings .flag {
  margin-right: var(--gap-m);
  font-size: var(--text-caption);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-quiet);
  border: 1px solid var(--edge);
  border-radius: 999px;
  padding: 0 var(--gap-s);
}

/* The meter being asked right now: an accent bar on the left of its own row,
   and a label beside its identity. The dot pulses, so the row is found at a
   glance in a long table. */
.readings tr.device.is-reading td { box-shadow: inset 4px 0 0 var(--accent); }
.readings .now {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-xs);
  margin-right: var(--gap-m);
  color: var(--accent);
  font-weight: 600;
}
.readings .now::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  animation: pulse 1s ease-in-out infinite alternate;
}
@keyframes pulse { from { opacity: 1; } to { opacity: 0.3; } }
@media (prefers-reduced-motion: reduce) { .readings .now::before { animation: none; } }

/* A quantity's row opens its chart. */
.readings tr.quantity { cursor: pointer; }
.readings tr.quantity:hover td { background: var(--page); }
.readings tr.quantity.is-open td { border-bottom-color: transparent; }
.readings td.chart { white-space: normal; padding-top: 0; }
.readings td.chart svg { display: block; width: 100%; height: 7.5rem; }
.readings td.chart polyline { fill: none; stroke: var(--accent); stroke-width: 2; vector-effect: non-scaling-stroke; }
.readings .chart-scale {
  display: flex;
  justify-content: space-between;
  font-size: var(--text-caption);
  color: var(--ink-faint);
}

/* A value that has moved since the first reading: the arrow and the colour say
   which way, and the number says how far. */
.readings .change { min-width: 8rem; }
.readings .rises { color: var(--good); font-family: var(--font-mono); font-weight: 600; }
.readings .falls { color: var(--falls); font-family: var(--font-mono); font-weight: 600; }
.readings .meter-mark { margin-right: var(--gap-m); cursor: default; }
/* A gauge's mark is a tilde, drawn larger than the table's text. At the
   table's size it is a faint stroke near the top of the line, where a
   counter's triangle is solid and easy to see. `line-height: 0` stops the
   larger glyph from making its row taller than a row carrying no mark:
   measured, a row grows from 29.4px to 37.6px without it, so only the rows
   that say something would have grown. */
.readings .moves {
  display: inline-block;
  vertical-align: middle;
  font-size: 1.5em;
  line-height: 0;
}
.readings .change span { cursor: default; }

#unresolved ul { margin: 0; padding-left: var(--gap-l); font-size: var(--text-small); }

/* How far the search is. The notice's own paragraphs keep no margin of their
   own, so the bar sits close under the sentence it belongs to. */
.notice p { margin: 0; }
.progress { margin-top: var(--gap-s); }
.progress .bar {
  height: 6px;
  background: var(--edge);
  border-radius: 999px;
  overflow: hidden;
}
.progress .done { height: 100%; width: 0; background: var(--accent); transition: width 0.4s ease; }
.progress .hint { margin-top: var(--gap-xs); font-size: var(--text-small); }

.wire { margin-top: var(--gap-l); }
.wire summary { cursor: pointer; color: var(--ink-quiet); font-size: var(--text-small); }
.wire pre {
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
  padding: var(--gap-m);
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  max-height: 20rem;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-all;
}

@media screen and (max-width: 640px) {
  body { padding: var(--gap-l) var(--gap-m); }
  .narrow, .minutes { width: 100%; }
  /* A phone has no room for two fields side by side, so the pair breaks and
     each of the two takes the width every other field has. */
  .row .pair { flex-wrap: wrap; }
  .row .pair > .field { flex: 1 1 100%; }
  .summary { gap: var(--gap-l); }
  /* **The masthead wraps.** A name, a role and two buttons do not fit 375px on
     one line, and a button whose label wraps inside a box of one height spills
     out of it -- which is the fault this bench's phone scan was written for.
     Found by that scan when Change my password was added beside Sign out
     (2026-09-20). */
  .who { flex-wrap: wrap; }
}

/* **What the node says of itself**, in four parts and three columns: the
   node, then its battery with its health under it, then its network. The
   gateway bench's parts, rule for rule, so a person who uses both benches reads
   one layout. Every part has all its rows, with a dash where the node did not
   say, so nothing moves as a read goes on.

   Three columns and not four, because four left each too narrow for its
   values: a date with its time, or two modes at once, took two lines. Battery
   and health are the two short parts, so they share the middle column. */
.node-parts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-areas:
    "node battery network"
    "node health network";
  /* The battery takes its own height, and the health starts right under it. */
  grid-template-rows: auto 1fr;
  align-items: start;
  gap: var(--gap-m) var(--gap-xl);
  margin: var(--gap-s) 0 var(--gap-l);
}
.node-part[data-part="node"] { grid-area: node; }
.node-part[data-part="battery"] { grid-area: battery; }
.node-part[data-part="health"] { grid-area: health; }
.node-part[data-part="network"] { grid-area: network; }
/* Too narrow for three side by side: two and two. */
@media (max-width: 1100px) {
  .node-parts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-areas:
      "node network"
      "battery network"
      "health network";
    grid-template-rows: auto auto 1fr;
    gap: var(--gap-m) var(--gap-l);
  }
}
/* And one under another on a phone. */
@media (max-width: 700px) {
  .node-parts {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "node" "battery" "health" "network";
    grid-template-rows: none;
  }
}
.node-part h3 {
  margin: 0 0 var(--gap-xs);
  font-size: var(--text-caption);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  font-weight: 600;
}
/* A name and its value on one line, the names in a column of their own. */
.node-part dl {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 2px var(--gap-m);
  margin: 0;
  font-size: var(--text-small);
}
.node-part dt { color: var(--ink-quiet); }
.node-part dd { margin: 0; overflow-wrap: break-word; font-family: var(--font-mono); }
.node-part dd.bad { color: var(--bad); }

/* A cell that says something is wrong: a node's fault, a meter's error, a link
   lost. The same red as the node's own parts. */
table.rows td.bad { color: var(--bad); }
/* A cell with more in its tooltip, such as twelve monthly averages. */
table.rows td[title]:not([title=""]) { cursor: help; text-decoration: underline dotted var(--ink-faint); text-underline-offset: 3px; }
/* The other nodes' table has thirteen columns: its headings may take two lines,
   so the table fits the page and its values stay on one. */
#node-levels .rows th { white-space: normal; vertical-align: bottom; }
/* A meter's state may be a whole sentence, such as three errors at once. It
   wraps within its own width rather than widening the table past the page. */
#node-list .rows th.state, #node-list .rows td.state { white-space: normal; min-width: 7rem; max-width: 13rem; }
/* A meter's last message may be many values; it wraps the same way. */
#node-list .rows th.message, #node-list .rows td.message { white-space: normal; min-width: 6rem; max-width: 13rem; }
/* The meter table has ten columns after the last messages are read: its
   headings may take two lines too, so the Remove buttons stay on the page. */
.rows:has(#node-meters) th { white-space: normal; vertical-align: bottom; }

/* The plan stays at the bottom of the window while the list above it is longer
   than the screen: a node may hold eighty meters, and a change put in a plan
   nobody can see looks like a button that does nothing. It scrolls inside
   itself where it is long. */
.plan {
  position: sticky;
  bottom: 0;
  z-index: 2;
  max-height: 50vh;
  overflow-y: auto;
  margin-top: var(--gap-l);
  padding: var(--gap-s) 0 var(--gap-m);
  background: var(--page);
  border-top: 1px solid var(--edge);
  box-shadow: 0 -8px 12px -10px rgba(0, 0, 0, 0.35);
}
/* A meter whose removal is in the plan. */
.rows tr.is-planned td:not(.action) { color: var(--ink-faint); text-decoration: line-through; }
/* The battery and the health share a column, so their names take one width
   and their values stand under each other. */
.node-part[data-part="battery"] dl,
.node-part[data-part="health"] dl { grid-template-columns: 10.5rem minmax(0, 1fr); }
@media (max-width: 1100px) {
  .node-part[data-part="battery"] dl,
  .node-part[data-part="health"] dl { grid-template-columns: max-content minmax(0, 1fr); }
}

/* A sentence beside a button stands at the button's middle. A row sets its
   contents on their lower edge, which is right for fields with a label above
   them and left this sentence a few pixels under the button's own words. */
.row > p.hint { align-self: center; margin: 0; }

/* **The account as one button and a menu, on a phone** (2026-10-04, as on the
   gateway bench). Somebody signed in had the name, the role, two buttons and
   Help above the page, on three or four lines. Now the title and one button
   with their name share a line, and the rest opens under the button.

   `.corner-items` wraps Help and the account, and `.who-line` the name and
   the role. On a wide screen neither has a box of its own, so the row is
   laid out as it was. */
.corner-items { display: contents; }
.who-line { display: contents; }
.account-open { display: none; }
@media screen and (max-width: 640px) {
  /* The title lines up with the words of the tabs under it. */
  body.signed-in .masthead { padding: 0 var(--gap-m); }
  body.signed-in .masthead .row.top { flex-wrap: nowrap; align-items: center; margin-bottom: var(--gap-m); }
  body.signed-in .masthead .grow { flex: 1 1 0; min-width: 0; }
  body.signed-in .masthead h1 { margin: 0; }
  /* The sentence under the title is for somebody who has not seen the page. */
  body.signed-in .masthead .lede { display: none; }
  body.signed-in .corner { position: relative; flex-wrap: nowrap; }
  body.signed-in .account-open { display: inline-flex; align-items: center; gap: var(--gap-s); white-space: nowrap; }
  body.signed-in .corner-items {
    display: none;
    position: absolute;
    right: 0;
    top: calc(100% + var(--gap-xs));
    z-index: 20;
    flex-direction: column;
    align-items: stretch;
    min-width: 13rem;
    padding: var(--gap-xs);
    background: var(--card);
    border: 1px solid var(--edge);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(23, 25, 28, 0.14);
  }
  body.signed-in .corner.is-open .corner-items { display: flex; }
  /* The account's own box goes, so its parts and Help are ordered as one list. */
  body.signed-in .corner .who { display: contents; }
  body.signed-in .corner .who-line {
    order: 1;
    display: flex;
    align-items: center;
    gap: var(--gap-s);
    margin: 0 0 var(--gap-xs);
    padding: var(--gap-s) var(--gap-m);
    border-bottom: 1px solid var(--edge);
    font-size: var(--text-small);
    color: var(--ink-quiet);
  }
  body.signed-in .corner #my-password { order: 2; }
  body.signed-in .corner .manual { order: 3; }
  body.signed-in .corner #signout { order: 4; }
  body.signed-in .corner-items button,
  body.signed-in .corner-items .manual {
    display: block;
    width: 100%;
    height: auto;
    padding: var(--gap-s) var(--gap-m);
    border: none;
    border-radius: 6px;
    background: none;
    color: var(--accent);
    font-size: var(--text-body);
    text-align: left;
  }
  body.signed-in .corner-items [hidden] { display: none; }
}

/* ==== own lists: begin ==== */
/* Every select is drawn by the page: a button that looks like a field, and a
   list that opens from it. Safari on a phone or a tablet draws a select's
   options in a narrow popover of its own, which no rule here can reach. The
   select itself stays in the page, hidden, and holds the value.

   This block is the same, byte for byte, in every bench. `--field` and
   `--field-pad` are what a bench sets where its own fields differ. */
select[data-own-list] { display: none !important; }
.choices { position: relative; display: block; width: 100%; }
button.choices-button {
  width: 100%;
  height: var(--control);
  display: flex;
  align-items: center;
  gap: var(--gap-s);
  padding: 0 var(--field-pad, var(--gap-m));
  font-family: var(--font);
  font-size: var(--text-small);
  font-weight: 400;
  color: var(--ink);
  background: var(--field, var(--card));
  border: 1px solid var(--edge);
  border-radius: 6px;
  text-align: left;
  cursor: pointer;
}
button.choices-button:hover { filter: none; border-color: var(--accent); }
button.choices-button[aria-expanded=true] { border-color: var(--accent); }
button.choices-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
button.choices-button[disabled] { cursor: default; border-color: var(--edge); }
/* `width: 0` and then grown: a long line must not make its field wider. With
   `min-width: 0` alone, a row of fields took the width of the chosen words
   and a phone scrolled sideways. */
.choices-now { flex: 1 1 0; width: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.choices-caret { flex: none; color: var(--ink-quiet); }
.choices-list {
  position: fixed;
  z-index: 1000;
  box-sizing: border-box;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--gap-xs) 0;
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.16);
}
.choices-group {
  padding: var(--gap-s) var(--gap-m) var(--gap-xs);
  font-size: var(--text-caption);
  color: var(--ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
/* A line wraps and is never cut: its end is often what tells two lines apart. */
.choices-list button {
  display: block;
  width: 100%;
  height: auto;
  min-height: var(--control);
  padding: var(--gap-s) var(--gap-m);
  font-family: var(--font);
  font-size: var(--text-small);
  font-weight: 400;
  line-height: 1.35;
  color: var(--ink);
  background: none;
  border: none;
  border-radius: 0;
  text-align: left;
  overflow-wrap: anywhere;
  cursor: pointer;
}
.choices-list button:hover, .choices-list button:focus-visible { filter: none; background: var(--page); outline: none; }
.choices-list button[aria-selected=true] { color: var(--accent); font-weight: 600; }
.choices-list button[disabled] { color: var(--ink-faint); cursor: default; background: none; }
/* ==== own lists: end ==== */

/* ==== own tooltips: begin ==== */
/* The page's own tooltip, the same text in three benches (see app.js). Fixed
   to the window, because a table that scrolls would cut it. It takes no
   pointer, so it is never in the way of what is under it. */
.own-tip {
  position: fixed;
  z-index: 1100;
  max-width: min(26rem, calc(100vw - 16px));
  padding: var(--gap-s) var(--gap-m);
  border-radius: 6px;
  background: var(--ink);
  color: var(--page);
  font-family: var(--font);
  font-size: var(--text-caption);
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  white-space: pre-line;
  pointer-events: none;
  box-shadow: 0 2px 10px rgb(0 0 0 / 0.25);
}
.own-tip[hidden] { display: none; }
/* In the top layer a browser centres a box and gives it a border and a
   scrollbar. This one is placed by the page and has neither. */
.own-tip[popover] { inset: auto; margin: 0; border: 0; overflow: visible; }
/* ==== own tooltips: end ==== */
