/* ============ tokens ============ */
:root {
  color-scheme: dark;
  --paper: #221f1b;
  --paper2: #2a2620;
  --paper3: #332e26;
  --ink: #efe9dc;
  --ink2: #b5ac9b;
  --ink3: #847c6d;
  --rule: #3a352c;
  --rule2: #4c453a;
  --accent: #d4ab2a;
  --accent-soft: #3a3423;
  /* ColorBrewer Paired (n=9); light/dark pairs carry related groups - see README */
  --g-core: #1f78b4;
  --g-aesthete: #ff7f00;
  --g-trials: #33a02c;
  --g-society: #fb9a99;
  --g-family: #e31a1c;
  --g-chaeronea: #cab2d6;
  --g-later: #fdbf6f;
  --g-beyond: #a6cee3;
  --g-liaisons: #b2df8a;
  --edge: #c8bfa6;
  --edge-soft: #847c6d;
  --ok: #3ec43e;
  --ok-bg: #20301d;
  --pend: #e2b83a;
  --pend-bg: #37301b;
  --warn: #e58a4a;
  --warn-bg: #382a1e;
  --bad: #e06060;
  --bad-bg: #3a2222;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  --serif:
    Georgia, "Iowan Old Style", "Palatino Linotype", "Book Antiqua", serif;
  --sans: system-ui, -apple-system, "Segoe UI", sans-serif;
}
/* ============ base ============ */
* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}
html,
body {
  margin: 0;
  height: 100%;
}
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
u {
  text-underline-offset: 5px;
}
/* A word the writer underlined twice, drawn as they drew it. The Complete Letters flatten this
   into the same italic as a single underline, and say so; where someone has read the manuscript,
   this is where the difference survives. */
u.u2 {
  text-decoration-style: double;
  text-underline-offset: 4px;
}
button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}
/* ============ header ============ */
header {
  flex: none;
  padding: 14px 20px 10px;
  border-bottom: 3.5px double var(--rule2);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 18px;
  background: var(--paper);
}
.masthead {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-right: auto;
}
.masthead h1 {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.masthead .sub {
  font-size: 12.5px;
  font-style: italic;
  color: var(--ink2);
}
.hstamp {
  font-family: var(--sans);
  font-size: 10.5px;
  color: var(--ink3);
  letter-spacing: 0.04em;
}
.hbtns {
  display: flex;
  gap: 8px;
  align-items: center;
}
.hbtn {
  font-family: var(--sans);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 6px 11px;
  border: 1px solid var(--rule2);
  border-radius: 999px;
  color: var(--ink2);
  background: var(--paper);
}
.hbtn:hover {
  border-color: var(--accent);
  color: var(--ink);
}
/* aria-expanded for the legend toggle, aria-pressed for the panels: different ARIA, same
   meaning to a reader — this button is the one currently doing something. */
.hbtn[aria-expanded="true"],
.hbtn[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--ink);
}
#search {
  font: italic 14px var(--serif);
  color: var(--ink);
  background: var(--paper2);
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 7px 30px 7px 14px;
  width: 286px;
}
#search::placeholder {
  color: var(--ink3);
}
/* ---- a search field's clear button -------------------------------------------------------
   Ours, not the browser's. Chromium shows its own only while the field is hovered or focused,
   Firefox shows none at all, and Safari's is a third thing again - so on two browsers out of
   three a reader can be left with a word in the box, a map narrowed to it, and nothing on
   screen offering to undo that. The native control is taken out and this put in its place, so
   the field behaves the same wherever it is read.

   Whether it shows is decided in CSS and needs no script: `:placeholder-shown` is the field
   being empty, so the button is hidden exactly while there is nothing to clear. */
.field {
  position: relative;
  display: flex;
  min-width: 0;
}
.field input::-webkit-search-cancel-button,
.field input::-webkit-search-decoration {
  -webkit-appearance: none;
  appearance: none;
}
.fieldclear {
  position: absolute;
  top: 50%;
  right: 9px;
  transform: translateY(-50%);
  width: 17px;
  height: 17px;
  display: grid;
  place-items: center;
  padding: 0;
  color: var(--ink3);
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}
/* The cross is DRAWN rather than typed. A "×" is centred by CSS on its em box, not on its ink,
   and the two do not coincide: in Segoe UI the ink sits 1.5px below the middle of the box, in
   Arial it sits dead centre. Since `system-ui` is a different face on every platform, a nudge
   that squared it here would be wrong on the next machine. Two strokes symmetrical about the
   middle of the viewBox are centred everywhere, and take their colour from the button. */
.fieldclear svg {
  display: block;
  width: 9px;
  height: 9px;
  overflow: visible;
}
.fieldclear svg path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
}
.fieldclear:hover,
.fieldclear:focus-visible {
  color: var(--ink);
  background: var(--rule2);
}
.field input:placeholder-shown ~ .fieldclear {
  display: none;
}
/* Room for it on each field that has one, so the text never runs underneath. Set on the fields
   themselves because `#search` is an id and would outrank anything written for `.field input`. */
.searchwrap {
  position: relative;
  display: flex;
  gap: 6px;
  align-items: center;
}
#searchscope {
  -webkit-appearance: none;
  appearance: none;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--ink2);
  background-color: var(--paper2);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23b5ac9b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 9px 5.5px;
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 6px 28px 6px 12px;
  cursor: pointer;
}
#searchscope:hover {
  border-color: var(--accent);
  color: var(--ink);
}
#searchnote {
  position: absolute;
  top: calc(100% + 5px);
  right: 0;
  z-index: 5;
  pointer-events: none;
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.03em;
  color: var(--ink2);
  background: var(--paper2);
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 2px 10px;
  white-space: nowrap;
}
#searchnote:empty {
  display: none;
}
#searchnote.clickable {
  pointer-events: auto;
  cursor: pointer;
  color: var(--ink);
  border-color: var(--rule);
}
#searchnote.clickable::before {
  content: "⌖  ";
  white-space: pre;
  opacity: 0.8;
  font-size: 12px;
  line-height: 1;
}
#searchnote.clickable:hover,
#searchnote.clickable:focus-visible {
  background: var(--paper);
  border-color: var(--accent, var(--ink2));
  color: var(--ink);
  outline: none;
}
#searchnote.clickable:active {
  transform: translateY(1px);
}
/* ============ legend ============ */
#legend {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  align-items: center;
  padding: 7px 20px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink2);
}
.lg-title {
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: 9.5px;
  color: var(--ink3);
  margin-right: -4px;
}
.lgc {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid transparent;
}
.lgc:hover {
  border-color: var(--rule2);
}
.lgc[aria-pressed="false"] {
  opacity: 0.35;
}
.lgc.solo {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
}
.lgc:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.lgc .dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
}
.lg-note {
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink3);
  border: 1px solid var(--rule2);
  border-radius: 3px;
  padding: 1px 4px;
  margin-left: 2px;
}
.lgc svg {
  flex: none;
}
.lg-sep {
  width: 1px;
  height: 16px;
  background: var(--rule2);
}
.lg-break {
  flex-basis: 100%;
  height: 0;
  margin: 0;
}
/* ============ main ============ */
main {
  flex: 1;
  display: flex;
  min-height: 0;
  position: relative;
}
#webwrap {
  flex: 1;
  min-width: 0;
  position: relative;
}
#web {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: none;
  display: block;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
#web.panning,
#web.panning * {
  cursor: grabbing;
}
#web .edge .e-hit {
  stroke: transparent;
  stroke-width: 16px;
  fill: none;
  cursor: pointer;
}
#web .edge .e-under {
  display: none;
  fill: none;
}
#web .edge .e-main {
  fill: none;
  stroke: var(--edge);
  cursor: pointer;
}
#web .edge.cert-married .e-under {
  display: block;
  stroke: var(--edge);
  stroke-width: 5;
}
#web .edge.cert-married .e-main {
  stroke: var(--paper);
  stroke-width: 1.8;
}
#web .edge.cert-self-reported .e-main {
  stroke-width: 1.8;
}
#web .edge.cert-second-hand .e-main {
  stroke-width: 1.8;
  stroke-dasharray: 7 5;
  opacity: 0.85;
}
#web .edge.cert-uncorroborated .e-main {
  stroke-width: 1.7;
  stroke-dasharray: 1 7;
  stroke-linecap: round;
  opacity: 0.85;
}
#web .edge.cert-attraction-expressed .e-main {
  stroke-width: 1.6;
  stroke-dasharray: 2 4 8 4;
  opacity: 0.85;
  marker-end: url(#arrowhead);
}
#web .edge.cert-attraction-expressed.out-unknown .e-main {
  stroke-width: 1.4;
  opacity: 0.55;
  marker-end: url(#arrowhead-open);
}
#web .edge.dimmed {
  opacity: 0.12;
}
#web .edge.hidden {
  display: none;
}
#web .edge.focus .e-main {
  stroke: var(--accent);
}
#web .edge.cert-married.focus .e-under {
  stroke: var(--accent);
}
#web.focusing .edge:not(.focus) {
  opacity: 0.09;
}
#web.focusing .node:not(.focus) {
  opacity: 0.13;
}
#web .node {
  cursor: pointer;
}
#web .node .shape,
#web .node .portrait {
  transition: transform 0.12s ease-out;
}
#web .node.armed {
  cursor: grabbing;
}
#web .node.armed .shape,
#web .node.armed .portrait {
  transform: scale(1.22);
}
@media (prefers-reduced-motion: reduce) {
  #web .node .shape,
  #web .node .portrait {
    transition: none;
  }
}
#web .node .shape {
  stroke: var(--ink);
  stroke-width: 1.4;
  fill: var(--ink3);
}
#web .node.g-core .shape {
  fill: var(--g-core);
}
#web .node.g-aesthete .shape {
  fill: var(--g-aesthete);
}
#web .node.g-trials .shape {
  fill: var(--g-trials);
}
#web .node.g-society .shape {
  fill: var(--g-society);
}
#web .node.g-family .shape {
  fill: var(--g-family);
}
#web .node.g-chaeronea .shape {
  fill: var(--g-chaeronea);
}
#web .node.g-later .shape {
  fill: var(--g-later);
}
#web .node.g-beyond .shape {
  fill: var(--g-beyond);
}
#web .node.g-liaisons .shape {
  fill: var(--g-liaisons);
}
#web .node text {
  font: 12px var(--serif);
  fill: var(--ink);
  paint-order: stroke;
  stroke: var(--paper);
  stroke-width: 3px;
  text-anchor: middle;
  pointer-events: none;
}
#web .node .pin {
  fill: var(--ink);
  stroke: var(--paper);
  stroke-width: 1;
  display: none;
}
#web .node.pinned .pin {
  display: block;
}
#web .node.leadonly {
  opacity: 0.15;
}
#web .node.dimmed {
  opacity: 0.15;
}
#web .node.dimmed.focus {
  opacity: 1;
}
#web .edge.dimmed.focus {
  opacity: 1;
}
#web .node.focus .shape {
  stroke: var(--accent);
  stroke-width: 3;
}
#tip {
  position: absolute;
  pointer-events: none;
  background: var(--paper2);
  border: 1px solid var(--rule2);
  border-radius: 6px;
  padding: 6px 10px;
  font-family: var(--sans);
  font-size: 11.5px;
  color: var(--ink2);
  box-shadow: var(--shadow);
  display: none;
  max-width: 260px;
  z-index: 5;
}
#tip b {
  color: var(--ink);
  font-weight: 600;
}
#emptymsg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink3);
  font-style: italic;
  padding: 30px;
  text-align: center;
}
#emptymsg[hidden] {
  display: none;
}
/* ============ panel ============ */
#panel {
  flex: none;
  width: 600px;
  max-width: 46vw;
  border-left: 1px solid var(--rule);
  background: var(--paper2);
  overflow-y: auto;
  display: none;
}
#panel.open {
  display: block;
}
.pwrap {
  padding: 0 20px 40px;
}
:root {
  --phead-h: 44px;
}
.phead {
  position: sticky;
  top: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  background: var(--paper2);
  margin: 0 -20px;
  padding: 16px 20px 8px;
}
.phead .grab {
  display: none;
}
.phtitle {
  flex: 1;
  min-width: 0;
  padding-right: 12px;
  line-height: 1.55;
  font-family: var(--serif);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.16s ease-out,
    visibility 0s linear 0.16s;
}
.phtitle.show {
  opacity: 1;
  visibility: visible;
  transition:
    opacity 0.16s ease-out,
    visibility 0s;
}
.phtitle a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule2);
}
.phtitle a:hover {
  color: var(--ink);
  border-bottom-color: var(--accent);
}
@media (prefers-reduced-motion: reduce) {
  .phtitle {
    transition: none;
  }
}
.pclose {
  float: right;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--ink3);
  padding: 4px 8px;
  border: 1px solid var(--rule2);
  border-radius: 999px;
}
.pclose:hover {
  color: var(--ink);
  border-color: var(--accent);
}
.ptag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink2);
  border: 1px solid var(--rule2);
  padding: 3px 9px;
  border-radius: 999px;
  margin-bottom: 6px;
  background: none;
  cursor: pointer;
  transition:
    border-color 0.12s,
    color 0.12s,
    background 0.12s;
}
.ptag:hover {
  border-color: var(--ink3);
  color: var(--ink);
}
.ptag:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.ptag .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
#panel h2 {
  margin: 2px 0 1px;
  font-size: 23px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
#panel h2 a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule2);
}
#panel h2 a:hover {
  border-color: var(--accent);
}
.aka {
  font-style: italic;
  color: var(--ink2);
  font-size: 13.5px;
}
.dates {
  font-family: var(--sans);
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
  color: var(--ink2);
  letter-spacing: 0.05em;
  margin: 2px 0 12px;
}
.bio {
  font-size: 14.5px;
  line-height: 1.62;
  max-width: 62ch;
}
.bionote {
  font-size: 11.5px;
  color: var(--ink3);
  font-style: italic;
  margin: 0 0 14px;
}
.method {
  margin: 22px 0 4px;
  border-top: 1px solid var(--rule);
  padding-top: 10px;
}
.method > summary {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink3);
  cursor: pointer;
  list-style: none;
}
.method > summary::-webkit-details-marker {
  display: none;
}
.method > summary::before {
  content: "▸";
  display: inline-block;
  margin-right: 6px;
  transition: transform 0.15s;
}
.method[open] > summary::before {
  transform: rotate(90deg);
}
.method > div {
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink3);
  margin-top: 8px;
  max-width: 62ch;
  white-space: pre-wrap;
}
.sect {
  position: sticky;
  top: var(--phead-h);
  z-index: 4;
  background: var(--paper2);
  padding-top: 4px;
  margin-top: -4px;
  padding-bottom: 4px;
  margin-bottom: 12px;
  padding-left: 20px;
  margin-left: -20px;
  padding-right: 20px;
  margin-right: -20px;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink3);
  border-bottom: 1px solid var(--rule);
}
/* timeline */
.tl {
  list-style: none;
  margin: 16px 0;
  padding: 0 0 0 3px;
}
.tl li {
  position: relative;
  padding: 7px 0 7px 22px;
}
.tl li .line {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -2px;
  width: 2px;
  border-left: 2px solid var(--rule2);
}
.tl li:last-child {
  padding-bottom: 2px;
}
.tl .knot {
  position: absolute;
  left: -6px;
  top: 3px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--edge);
  border: 2px solid var(--paper2);
}
.tl li.anchor .knot {
  background: var(--paper2);
  border: 2px solid var(--ink3);
}
.tl li.sx .knot {
  background: var(--paper2);
  border: 2px solid var(--edge);
}
/* A chronology entry: the volume's own fixed points, set against the engagements rather than
   among them - right-aligned, quieter, and with no knot on the line, because nothing here is
   a connection this map is making. */
.tl li.era {
  color: var(--ink3);
}
.tl li.era .what {
  font-style: italic;
}
/* One of the volume's own periods opening - OXFORD, LONDON I, PRISON. It divides the
   timeline rather than sitting on it, so it takes the whole width, carries no date of its
   own, and rules out to both edges. */
.tl li.epoch {
  position: sticky;
  top: calc(var(--phead-h) + 24px);
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--ink3);
}
.tl li.epoch::before,
.tl li.epoch::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule2);
}
.tl li.epoch .knot,
.tl li.epoch .when {
  display: none;
}
.tl li.epoch .what {
  flex: 0 0 auto;
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.tl li.era .knot {
  background: transparent;
  border-color: var(--rule2);
}
.tl .when {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.05em;
  color: var(--ink3);
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
}
.tl .what {
  font-size: 14px;
  line-height: 1.45;
}
.tl .what a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule2);
}
.tl .what a:hover {
  border-color: var(--accent);
}
.tl li.anchor .what {
  font-style: italic;
  color: var(--ink2);
}
.tl .offr {
  font-family: var(--sans);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  color: var(--ink3);
  text-transform: uppercase;
  margin-left: 5px;
}
.mini {
  display: inline-block;
  vertical-align: 1px;
  margin-left: 7px;
}
.mini-plat {
  display: inline-block;
  margin-left: 7px;
  font-family: var(--sans);
  font-size: 8.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink3);
  border: 1px solid var(--rule2);
  border-radius: 3px;
  padding: 1px 5px;
  white-space: nowrap;
  user-select: none;
}
/* relationship card */
.rhead {
  font-size: 20px;
  margin: 2px 0 2px;
}
.badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink2);
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 4px 11px;
  margin: 7px 8px 7px 0;
}
.badge .prov {
  font-size: 9.5px;
  color: var(--ink3);
  font-style: italic;
  text-transform: none;
  letter-spacing: 0;
}
.datesline {
  font-family: var(--sans);
  font-size: 12.5px;
  color: var(--ink2);
  margin: 2px 0 10px;
  font-variant-numeric: tabular-nums;
}
.summary {
  font-size: 14.5px;
  line-height: 1.6;
  max-width: 62ch;
  margin: 0 0 8px;
}
.disputed {
  border-left: 3px solid var(--pend);
  background: var(--pend-bg);
  padding: 10px 13px;
  border-radius: 0 6px 6px 0;
  font-size: 13px;
  line-height: 1.55;
  margin: 12px 0;
}
.disputed .dline {
  margin-top: 7px;
}
.disputed .dline > span {
  display: block;
  font-family: var(--sans);
  font-size: 9.5px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink3);
  margin-bottom: 1px;
}
.disputed b {
  letter-spacing: 0.03em;
}
/* quotes */
.qcard {
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--paper);
  padding: 13px 15px 11px;
  margin: 0 0 12px;
  box-shadow: 0 1px 0 var(--rule);
}
.qctx {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.02em;
  line-height: 1.5;
  color: var(--ink3);
  margin-bottom: 7px;
}
.qctx.long {
}
/* The document's own header sentence, generated from the record and set at the head of the
   context paragraph: who wrote to whom, when, from where. A shade brighter than the
   commentary that follows it, so the eye can take the identity in one line. */
.qctx-h {
  color: var(--ink2);
}
/* Each level of the place the heading names, worn as a link rather than a chip: the heading is
   a sentence, and a row of chips set into the middle of it would stop it being one. Underlined
   like the person links a line below, because it does what they do - takes you to the rest of
   its kind - and lit in the accent once it is soloing, as every other filter control is. */
.qplace {
  border-bottom: 1px solid var(--rule2);
  vertical-align: baseline;
}
.qplace:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.qplace[aria-pressed="true"] {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
/* The age beside a correspondent's name: derived from this map's own birth dates, not
   printed by the volume, so it reads a shade quieter than the name it follows. */
.qage {
  color: var(--ink3);
}
.qcard blockquote {
  margin: 0 0 9px;
  font-size: 14.5px;
  line-height: 1.62;
  white-space: pre-wrap;
  padding-left: 12px;
  border-left: 2px solid var(--rule2);
}
/* A quotation clipped because it would bury the card: the veil says the text continues,
   rather than the text simply stopping. */
.qcard blockquote.qclip {
  max-height: 26em;
  overflow: hidden;
  position: relative;
}
.qcard blockquote.qclip .qveil {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 5em;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--paper));
  pointer-events: none;
}
.qcard button.qmore {
  display: block;
  width: 100%;
  margin: 0 0 10px;
  padding: 6px 10px;
  font-family: var(--sans);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--ink2);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 6px;
  cursor: pointer;
}
.qcard button.qmore:hover {
  color: var(--ink);
  border-color: var(--rule2);
}
.qcard .qmore-n {
  color: var(--ink3);
}
.qcard blockquote.q-period {
  position: relative;
  border-left: none;
  padding: 3px 22px 3px 29px;
  margin: 6px 0 12px;
}
.qcard blockquote.q-period::before,
.qcard blockquote.q-period::after {
  position: absolute;
  font-family: var(--serif);
  font-size: 40px;
  line-height: 1;
  color: var(--ink3);
  opacity: 0.32;
  pointer-events: none;
}
.qcard blockquote.q-period::before {
  content: "\201C";
  left: 0;
  top: -4px;
}
.qcard blockquote.q-period::after {
  content: "\201D";
  right: 2px;
  bottom: -18px;
}
.qcard blockquote.q-court {
  border-left: 2px dashed var(--rule2);
  padding: 2px 0 2px 13px;
  margin: 6px 0 12px;
  display: block;
}
.qcard blockquote.q-court .who {
  display: block;
  margin: 0 0 1px;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink3);
}
.qcard blockquote.q-court .who:empty {
  display: none;
}
.qcard blockquote.q-court .said {
  display: block;
  margin: 0 0 10px;
}
.qcard blockquote.q-court .said:last-child {
  margin-bottom: 0;
}
.qtrans {
  /* A lineated translation sits under a lineated quotation; without this its lines run
     together into prose and stop answering the original line for line. */
  white-space: pre-wrap;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink2);
  margin: -2px 0 10px;
  padding-left: 12px;
  border-left: 1px solid var(--rule2);
}
.qtrans-h {
  display: block;
  font-family: var(--sans);
  font-size: 9.5px;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink3);
  margin-bottom: 3px;
}
.qtrans-n {
  display: block;
  font-size: 11.5px;
  font-style: italic;
  color: var(--ink3);
  margin-top: 5px;
}
.qattr {
  font-size: 12.5px;
  color: var(--ink2);
  margin-bottom: 9px;
}
.qplaced {
  font-size: 0.82em;
  font-style: italic;
  color: var(--ink3);
  margin-top: 0.35em;
  opacity: 0.9;
}
.qsupports {
  font-size: 11.5px;
  color: var(--ink3);
  font-style: italic;
  margin-bottom: 9px;
}
/* One quotation cited by several connections: each note and each claim keeps its own line and
   its own name, rather than being run together into a paragraph that would read as one voice. */
.qnote,
.qsup {
  display: block;
}
.qnote + .qnote,
.qsup + .qsup {
  margin-top: 5px;
}
.qnote-w {
  font-style: normal;
  color: var(--ink2);
}
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--sans);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  border-radius: 4px;
  padding: 3px 8px;
}
.chip.v-ok {
  color: var(--ok);
  background: var(--ok-bg);
}
.chip.v-pend {
  color: var(--pend);
  background: var(--pend-bg);
}
.chip.v-warn {
  color: var(--warn);
  background: var(--warn-bg);
}
.chip.v-bad {
  color: var(--bad);
  background: var(--bad-bg);
}
.chip.how {
  color: var(--ink2);
  background: var(--paper3);
  font-weight: 400;
}
.qcard details {
  margin-top: 9px;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink2);
}
.qcard summary {
  cursor: pointer;
  color: var(--ink3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 9.5px;
}
.qcard details div {
  margin-top: 5px;
  line-height: 1.5;
}
.qpointer {
  border-style: dashed;
  background: var(--paper2);
}
.qpointer .qhead {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pend);
  margin-bottom: 6px;
}
.qpointer .qclaim {
  font-size: 13.5px;
  font-style: italic;
  line-height: 1.55;
  margin-bottom: 8px;
}
/* list view */
.lrow {
  display: block;
  width: 100%;
  text-align: left;
  padding: 9px 4px;
  border-bottom: 1px solid var(--rule);
  font-size: 13.5px;
  line-height: 1.4;
}
.lrow:hover {
  background: var(--paper3);
}
.lrow .when {
  font-family: var(--sans);
  font-size: 10.5px;
  color: var(--ink3);
  letter-spacing: 0.05em;
  font-variant-numeric: tabular-nums;
  text-transform: uppercase;
}
.lrow .vs {
  font-family: var(--sans);
  font-size: 10px;
  color: var(--ink3);
  margin-left: 8px;
}
/* about modal */
#about {
  position: fixed;
  inset: 0;
  background: rgba(20, 17, 12, 0.55);
  display: none;
  z-index: 20;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
#about.open {
  display: flex;
}
.abox {
  background: var(--paper);
  border: 1px solid var(--rule2);
  border-radius: 10px;
  max-width: 620px;
  max-height: 86vh;
  overflow-y: auto;
  padding: 26px 30px;
  box-shadow: var(--shadow);
}
.abox h2 {
  margin: 0 0 4px;
  font-size: 17px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.abox p,
.abox li {
  font-size: 13.5px;
  line-height: 1.62;
  color: var(--ink2);
}
.lkey {
  list-style: none;
  margin-left: -1.55em;
  padding-left: 2.9em;
  padding-top: 0.5em;
  padding-bottom: 0.5em;
  text-indent: -2.9em;
}
.lkey .lsample {
  margin-right: 8px;
  vertical-align: -1px;
}
.lkey > b:first-of-type {
  text-indent: 0;
}
.abox b {
  color: var(--ink);
}
.abox .sect {
  margin-top: 16px;
}
/* responsive */
@media (max-width: 900px) {
  #panel {
    position: fixed;
    inset: 0;
    width: 100%;
    max-width: none;
    height: 100%;
    border-left: none;
    box-shadow: var(--shadow);
    z-index: 10;
  }
  .searchwrap {
    flex-basis: 100%;
  }
  #search {
    flex: 1;
    width: auto;
    min-width: 0;
  }
  .pwrap {
    padding-top: 0;
  }
  .phead {
    padding: 14px 20px 10px;
  }
  .phead .grab {
    display: block;
    position: absolute;
    left: 50%;
    top: 5px;
    transform: translateX(-50%);
    width: 46px;
    height: 5px;
    border-radius: 3px;
    background: var(--rule2);
    touch-action: none;
    cursor: grab;
  }
  .phead .grab:active {
    cursor: grabbing;
    background: var(--ink3);
  }
  header {
    padding: 10px 14px 8px;
  }
  .masthead h1 {
    font-size: 16px;
  }
}
@media (min-width: 901px) {
  #panel {
    display: block;
  }
}
@media (prefers-reduced-motion: reduce) {
  * {
    scroll-behavior: auto !important;
  }
}

#web .node.has-portrait .shape {
  fill: none;
  stroke-width: 3.2;
  pointer-events: all;
}
#web .node.g-core.has-portrait .shape {
  stroke: var(--g-core);
}
#web .node.g-aesthete.has-portrait .shape {
  stroke: var(--g-aesthete);
}
#web .node.g-trials.has-portrait .shape {
  stroke: var(--g-trials);
}
#web .node.g-society.has-portrait .shape {
  stroke: var(--g-society);
}
#web .node.g-family.has-portrait .shape {
  stroke: var(--g-family);
}
#web .node.g-chaeronea.has-portrait .shape {
  stroke: var(--g-chaeronea);
}
#web .node.g-later.has-portrait .shape {
  stroke: var(--g-later);
}
#web .node.g-liaisons.has-portrait .shape {
  stroke: var(--g-liaisons);
}
#web .node.g-beyond.has-portrait .shape {
  stroke: var(--g-beyond);
}
#web .node.has-portrait.focus .shape {
  stroke: var(--accent);
  stroke-width: 4;
}
#web .node .portrait {
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s ease;
}
#web .node .portrait.loaded {
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  #web .node .portrait {
    opacity: 1;
    transition: none;
  }
}

.dates .ext {
  color: var(--ink3);
  text-decoration: none;
  border-bottom: 1px dotted var(--rule2);
}
.dates .ext:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.dates .ext::after {
  content: "↗";
  font-size: 0.8em;
  margin-left: 3px;
  vertical-align: 1px;
}

.qspeaker {
  font-family: var(--serif);
  font-size: 15.5px;
  color: var(--ink);
  margin: 0 0 5px;
  line-height: 1.25;
}
.qlink {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule2);
}
.qlink:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.qdate {
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--ink3);
  margin-left: auto;
  padding-left: 1em;
  white-space: nowrap;
}
.qspeaker-to {
  font-size: 12px;
  font-style: italic;
  color: var(--ink3);
  font-family: var(--serif);
  white-space: pre;
}
.qspeaker-x {
  font-size: 12.5px;
  font-style: italic;
  color: var(--ink2);
}
.qwith {
  margin: 0 0 0.6em;
  padding-bottom: 0.45em;
  border-bottom: 1px dotted var(--rule2);
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.03em;
  color: var(--ink3);
  display: flex;
  align-items: center;
  gap: 6px;
}
.qwith a {
  color: var(--ink2);
  text-decoration: none;
  border-bottom: 1px solid var(--rule2);
}
.qwith a:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.sect-note {
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.5;
  color: var(--ink3);
  margin: 4px 0;
}
.pgroup {
  margin: 0 0 18px;
}
.pgroup-h {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 8px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--rule);
}
.pgroup-h a {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--rule2);
}
.pgroup-h a:hover {
  border-bottom-color: var(--accent);
  color: var(--accent);
}
.pgroup-n {
  margin-left: auto;
  font-family: var(--sans);
  font-size: 10px;
  color: var(--ink3);
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 1px 7px;
}

#web .node:focus {
  outline: none;
}
#web .node.primary .shape {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
  border-radius: 3px;
}
#web .node:focus-visible:not(.primary) .shape {
  outline: 2px dashed var(--ink);
  outline-offset: 6px;
  border-radius: 3px;
}
#web .node.dimmed:focus-visible,
#web.focusing .node:not(.focus):focus-visible {
  opacity: 0.55;
}
.sfq {
  width: 100%;
  box-sizing: border-box;
  font: italic 13.5px var(--serif);
  color: var(--ink);
  background: var(--paper2);
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 6px 30px 6px 13px;
}
.sfq::placeholder {
  color: var(--ink3);
}
.sfq::-webkit-search-cancel-button {
  filter: invert(0.55) sepia(0.3);
}
.sfrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.sfyears {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.sfselects {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.sfyl {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink3);
}
.sfy {
  width: 52px;
  font: 12.5px var(--sans);
  color: var(--ink);
  background: var(--paper2);
  border: 1px solid var(--rule2);
  border-radius: 5px;
  padding: 4px 6px;
  text-align: center;
}
.sfy::placeholder {
  color: var(--ink3);
}
.sfdash {
  color: var(--ink3);
  font-size: 12px;
  margin: 0 -2px;
}
.sfdoc {
  margin-left: auto;
  position: relative;
  font: 11.5px var(--sans);
  color: var(--ink2);
}
/* Closed, it reads as the pill the select used to be. Open, it drops a panel of checkboxes:
   twenty-one kinds is too many for a native multiple select, whose only affordance is
   ctrl-clicking a tall box. `details` is the disclosure this site already uses elsewhere, so it
   comes with the keyboard behaviour and needs no popover machinery. */
.sfdoc > summary {
  list-style: none;
  cursor: pointer;
  max-width: 100%;
  background: var(--paper2);
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 3px 22px 3px 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sfdoc > summary::-webkit-details-marker {
  display: none;
}
.sfdoc > summary::after {
  content: "";
  position: absolute;
  right: 9px;
  top: 9px;
  width: 0;
  height: 0;
  border: 4px solid transparent;
  border-top-color: var(--ink2);
}
.sfdoc[open] > summary::after {
  transform: rotate(180deg);
  top: 5px;
}
.sfdoc > summary:hover {
  color: var(--ink);
  border-color: var(--accent);
}
.sfdoc[data-empty] > summary {
  opacity: 0.4;
  pointer-events: none;
}
/* Floated over the sources rather than pushing them down: a list of twenty-one would shove the
   first card off the screen every time the box was opened. */
.sfdocbox {
  position: absolute;
  right: 0;
  z-index: 6;
  min-width: 190px;
  max-height: 46vh;
  overflow-y: auto;
  margin-top: 4px;
  padding: 5px;
  background: var(--paper2);
  border: 1px solid var(--rule2);
  border-radius: 8px;
  box-shadow: var(--shadow);
}
.sfdocopt {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 3px 6px;
  border-radius: 5px;
  cursor: pointer;
}
.sfdocopt:hover {
  background: var(--paper3);
  color: var(--ink);
}
.sfdocopt span {
  flex: 1 1 auto;
}
.sfdocopt b {
  font-weight: 400;
  color: var(--ink3);
}
.sfdocopt input {
  accent-color: var(--accent);
  margin: 0;
}
/* Ruled off from the kinds below it: it acts on all of them rather than being one of them. */
.sfdocall {
  border-bottom: 1px solid var(--rule);
  border-radius: 5px 5px 0 0;
  margin-bottom: 3px;
  padding-bottom: 5px;
  color: var(--ink2);
}
.sfdocall span {
  letter-spacing: 0.04em;
}
.sfdoc.on > summary {
  color: var(--accent);
  border-color: var(--accent);
}
.sfdoc.on > summary::after {
  border-top-color: var(--accent);
}
.sfclear {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.03em;
  color: var(--ink2);
  background: var(--paper2);
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 3px 9px;
  cursor: pointer;
}
.sfclear:hover {
  border-color: var(--accent);
  color: var(--ink);
}
.sfcount {
  position: absolute;
  top: 50%;
  right: 32px;
  transform: translateY(-50%);
  font-family: var(--sans);
  font-size: 10.5px;
  line-height: 1;
  color: var(--ink3);
  background: var(--paper2);
  padding: 3px 0 3px 8px;
  border-radius: 999px;
  pointer-events: none;
}
.sfq:placeholder-shown + .sfcount {
  right: 13px;
}
.sfqfield.counting .sfq::placeholder {
  opacity: 0;
}
.sfnone {
  margin: 0 0 12px;
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.55;
  color: var(--ink3);
  border-left: 2px solid var(--rule2);
  padding-left: 10px;
}
.qcard.sfhide {
  display: none;
}
mark.sfhit {
  background: rgba(212, 171, 42, 0.2);
  color: inherit;
  border-radius: 2px;
  padding: 0;
  box-shadow:
    0 0 0 1.5px rgba(212, 171, 42, 0.2),
    0 0 0 2.5px rgba(212, 171, 42, 0.22);
}
.qcard blockquote mark.sfhit {
  background: rgba(212, 171, 42, 0.24);
}
.qlink mark.sfhit {
  background: rgba(212, 171, 42, 0.26);
}
.qcard details.sfdeep > summary {
  color: var(--accent);
}
.qcard details.sfdeep > summary::after {
  content: " — match inside";
  font-family: var(--sans);
  font-size: 9.5px;
  letter-spacing: 0.04em;
  color: var(--accent);
  opacity: 0.85;
}
#mapctl {
  position: absolute;
  left: 14px;
  bottom: 14px;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  background: var(--paper);
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 13px 7px;
  box-shadow: var(--shadow);
}
#btnFit {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink2);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
#btnFit:hover {
  color: var(--accent);
}
#mapctl .sep {
  width: 15px;
  height: 1px;
  background: var(--rule2);
}
#zoomRange {
  -webkit-appearance: none;
  appearance: none;
  writing-mode: vertical-lr;
  direction: rtl;
  width: 13px;
  height: 108px;
  background: none;
  cursor: pointer;
  margin: 0;
  padding: 0;
}
#zoomRange::-webkit-slider-runnable-track {
  width: 2px;
  height: 100%;
  background: var(--rule2);
  border-radius: 2px;
}
#zoomRange::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--ink2);
  border: 0;
  margin-left: -4.5px;
}
#zoomRange:hover::-webkit-slider-thumb,
#zoomRange:focus-visible::-webkit-slider-thumb {
  background: var(--accent);
}
#zoomRange::-moz-range-track {
  width: 2px;
  height: 100%;
  background: var(--rule2);
  border-radius: 2px;
}
#zoomRange::-moz-range-thumb {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--ink2);
  border: 0;
}
#zoomRange:hover::-moz-range-thumb,
#zoomRange:focus-visible::-moz-range-thumb {
  background: var(--accent);
}
@media (max-width: 900px) {
  #mapctl {
    left: 10px;
    bottom: 10px;
    padding: 11px 6px;
    gap: 7px;
  }
  #zoomRange {
    height: 88px;
  }
}
#panel:not(:has(.phead)) .pwrap > *:first-child:not(.sect) {
  padding-top: 18px;
}
#panel:not(:has(.phead)) .sect {
  top: 0;
  margin-top: 4px;
  padding-top: 16px;
}
#panel:not(:has(.phead)) .sfilter {
  top: 35px;
}
#panel .sfilter {
  position: sticky;
  top: calc(var(--phead-h) + 28px);
  z-index: 3;
  margin-left: -20px;
  margin-right: -20px;
  padding-left: 20px;
  padding-right: 20px;
  padding-bottom: 8px;
}
#panel .bg {
  position: absolute;
  inset: -12px 4px 0 4px;
  z-index: -1;
  background: var(--paper2);
}
#panel .sfnone {
  position: relative;
  z-index: 2;
}
#web .node.armed .shape,
#web .node.armed.has-portrait .shape {
  stroke: var(--accent);
  stroke-width: 3.4;
}
.qwith .noedge {
  margin-left: 7px;
  font-family: var(--sans);
  font-size: 8.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink3);
  border: 1px solid var(--rule2);
  border-radius: 3px;
  padding: 1px 5px;
  white-space: nowrap;
  user-select: none;
}
.qwith a.noedge {
  color: var(--ink2);
  border-color: var(--rule);
  text-decoration: none;
  cursor: pointer;
}
.qwith a.noedge:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* Contributing panel
   Scoped to .doc so the code, table and rule styles reach only the compiled CONTRIBUTING.md and
   cannot leak into a person panel, where <code> and <table> mean something else. Every wide
   construct scrolls inside its own box: the panel itself must never scroll sideways. */
/* Subordinate to .sect, which is what `##` becomes. Uppercase at a larger size read as the
   senior of the two, which is backwards, so this stays sentence-case and takes its weight from
   the serif instead. */
#panel.doc h3 {
  font-family: var(--serif);
  font-size: 15px;
  font-weight: 600;
  font-style: italic;
  color: var(--ink);
  margin: 20px 0 6px;
}
#panel.doc hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 22px 0;
}

#panel th,
#panel td {
  border-bottom: 1px solid var(--rule);
  padding: 10px 9px;
  text-align: left;
  vertical-align: top;
}
#panel thead th {
  border-bottom: 2px solid var(--rule);
}
#panel th {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink3);
  font-weight: 500;
  white-space: nowrap;
}

#panel.doc pre {
  overflow-x: auto;
  background: rgba(0, 0, 0, 0.24);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 9px 11px;
  margin: 10px 0;
}
#panel.doc pre code {
  background: none;
  border: 0;
  padding: 0;
  white-space: pre;
}
code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.85em;
  color: var(--ink2);
  background: rgba(0, 0, 0, 0.24);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 0.2em 0.4em;
  font-weight: 500;
  white-space: nowrap;
}

#panel.doc table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.5; /* Essential for large blocks of text */
  margin: 16px 0;
}
/* Code tokens, coloured by tools/validate.py at build time, kept inside the page's warm range
   rather than a stock editor theme. */
#panel.doc .t-com {
  color: var(--ink3);
  font-style: italic;
}
#panel.doc .t-key {
  color: var(--accent);
}
#panel.doc .t-str {
  color: #a3b98d;
}
#panel.doc .t-num,
#panel.doc .t-kw {
  color: #9fb2cd;
}
#panel.doc .t-flag {
  color: var(--accent);
}
#panel.doc .t-cmd {
  color: var(--ink);
}

/* Collapsible legend on small screens: it is a key you consult now and then, not a control you
   keep open, so it folds away by default and the map gets the space. Desktop is untouched. */
#btnLegend {
  display: none;
}
@media (max-width: 900px) {
  #btnLegend {
    display: inline-block;
  }
  #legend {
    display: none;
  }
  #legend.open {
    display: flex;
  }
}

@media (max-width: 900px) {
  /* Four buttons do not fit on one 375px row; wrapping beats shrinking the type, which would
     make every button harder to hit on the device where hitting them is hardest. */
  .hbtns {
    flex-wrap: wrap;
  }
  header {
    padding: 10px 14px 8px;
    gap: 6px 12px;
  }
  /* The build stamp is provenance, not navigation. It stays available but stops taking two lines
     from the map at the top of a phone screen. */
  .hstamp {
    font-size: 9.5px;
    line-height: 1.35;
  }
  .masthead h1 {
    font-size: 16px;
    letter-spacing: 0.16em;
  }
  .masthead .sub {
    font-size: 11.5px;
  }
  #search {
    width: 100%;
  }
  .searchwrap {
    flex: 1 1 100%;
  }
}

/* Connection header: two cells, names and date.
   The names cell wraps; the date holds one line at the right. align-items is flex-start rather
   than center so a two-line list of names does not drag the date down to sit between them. */
.qwith {
  align-items: flex-start;
  flex-wrap: nowrap;
}
.qwith .qnames {
  flex: 1 1 auto;
  min-width: 0;
  line-height: 1.6;
}
.qwith .qdate {
  flex: 0 0 auto;
  margin-left: auto;
}

/* A name and its line-sample are one unit and never break apart across a wrap. */
.qwith .qpair {
  display: inline-block;
  white-space: nowrap;
}

/* Scope selector on the sources filter. Mirrors the header search's Names/Quotations/All so the
   two searches behave the same way, and shares the header select's chevron so they read as one
   control family. */
.sfqwrap {
  display: flex;
  gap: 6px;
  align-items: center;
}
.sfqfield {
  position: relative;
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
}
.sfqwrap .sfq {
  flex: 1 1 auto;
  min-width: 0;
}
.sfscope {
  -webkit-appearance: none;
  appearance: none;
  flex: 0 0 auto;
  font-family: var(--sans);
  font-size: 10.5px;
  letter-spacing: 0.03em;
  color: var(--ink2);
  background-color: var(--paper2);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23b5ac9b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 8px 5px;
  border: 1px solid var(--rule2);
  border-radius: 999px;
  padding: 5px 24px 5px 10px;
  cursor: pointer;
}
.sfscope:hover {
  border-color: var(--accent);
  color: var(--ink);
}

/* Tapping a control should not select its label.
   -webkit-tap-highlight-color kills the flash Android draws on tap, but not the text selection
   that a tap on a word can start - which paints the same blue and stays until you tap elsewhere.
   Applied to controls only: prose, quotations and citations must stay selectable, since copying
   a quotation out is a thing readers of this map actually do. */
button,
.hbtn,
.lgc,
.pclose,
.sfclear,
#searchnote.clickable,
#btnFit,
.lrow,
label,
select,
summary {
  -webkit-user-select: none;
  user-select: none;
}
/* The map's own selection colour, for the text that IS selectable - the browser default is a
   blue that belongs to no part of this palette. */
::selection {
  background: var(--accent-soft);
  color: var(--ink);
}

/* ============ manuscript reader ============ */
/* A quotation that cites scanned pages carries a control back to the document itself. It sits
   with the verification chips rather than in the card's body: it is a statement about how the
   text was checked, not part of the text. */
.qfacs {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--sans);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  border: 1px solid var(--rule2);
  border-radius: 4px;
  padding: 2px 8px;
  color: var(--ink2);
}
.qfacs:hover {
  color: var(--ink);
  border-color: var(--accent);
}
.qfacs-i {
  width: 11px;
  height: 11px;
  flex: none;
  opacity: 0.8;
  overflow: visible;
}
.qfacs:hover .qfacs-i {
  opacity: 1;
}

#facs {
  position: fixed;
  inset: 0;
  z-index: 40;
  /* Opaque, not a veil. At 94% the panel's own headings and body text still read through from
     underneath, and a page of handwriting is hard enough without a second page behind it. */
  background: #100e0b;
  display: grid;
  /* bar / page / citation / thumbnails. The page takes everything left over, so a tall scan and
     a wide one both open filling the same frame. */
  grid-template-rows: auto minmax(0, 1fr) auto auto;
}
#facs[hidden] {
  display: none;
}
.fbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--rule);
}
.ftitle {
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 12px;
}
.fname {
  font-family: var(--serif);
  font-size: 14px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fpager {
  flex: none;
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink3);
}
.fbtns {
  display: flex;
  gap: 6px;
  flex: none;
}
.fbtn {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink2);
  padding: 4px 10px;
  border: 1px solid var(--rule2);
  border-radius: 999px;
  line-height: 1.4;
}
.fbtn:hover:not(:disabled) {
  color: var(--ink);
  border-color: var(--accent);
}
.fbtn:disabled {
  opacity: 0.32;
  cursor: default;
}
.fbtn[aria-pressed="true"] {
  color: var(--accent);
  border-color: var(--accent);
}

.fstage {
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  cursor: zoom-in;
}
.fstage.zoomed {
  /* Zoomed, the stage becomes a window onto a bigger sheet and the reader drags it around;
     centring would fight the scroll position. */
  display: block;
  overflow: auto;
  cursor: grab;
  padding: 0;
}
.fstage.zoomed.dragging {
  cursor: grabbing;
}
#facsImg {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  /* Paper, not a photograph: the scans are near-white and a hairline keeps the sheet's edge from
     bleeding into the backdrop. */
  border: 1px solid var(--rule);
  background: #f4efe4;
  -webkit-user-select: none;
  user-select: none;
}
.fstage.zoomed #facsImg {
  max-width: none;
  max-height: none;
  border: 0;
}
.fstage.loading #facsImg {
  opacity: 0.25;
  transition: opacity 0.2s ease-out;
}

.ffoot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 9px 16px;
  border-top: 1px solid var(--rule);
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.5;
  color: var(--ink3);
}
.fcite {
  min-width: 0;
}
.fcite b {
  font-weight: 600;
  color: var(--ink2);
  letter-spacing: 0.04em;
}
.fcite a,
.frights a {
  color: var(--ink2);
  text-decoration: none;
  border-bottom: 1px solid var(--rule2);
}
.fcite a:hover,
.frights a:hover {
  color: var(--ink);
  border-bottom-color: var(--accent);
}
.frights {
  flex: none;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* Undetermined is not a warning and is not styled as one - it is the archive saying the question
   has not been resolved, which a reader reusing the image needs to know before they do. */
.frights .rmark {
  color: var(--ink2);
  border: 1px solid var(--rule2);
  border-radius: 4px;
  padding: 2px 7px;
  margin-right: 6px;
}
.frights .rmark.rnoc {
  color: var(--ok);
  border-color: var(--ok);
}

.fthumbs {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 8px 16px 10px;
  border-top: 1px solid var(--rule);
  scrollbar-width: thin;
}
.fthumbs:empty {
  display: none;
}
.fthumb {
  flex: none;
  width: 54px;
  height: 42px;
  padding: 0;
  border: 1px solid var(--rule2);
  border-radius: 2px;
  overflow: hidden;
  opacity: 0.5;
  background: #f4efe4;
}
.fthumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.fthumb:hover {
  opacity: 0.85;
}
.fthumb[aria-current="true"] {
  opacity: 1;
  border-color: var(--accent);
}
/* The pages of the letter being quoted come first and the rest of the archival folder after, so
   a reader can walk the whole item without losing which sheets the quotation rests on. */
.fthumb.frest {
  filter: grayscale(0.5);
}
.fthumbs .fgap {
  flex: none;
  align-self: center;
  font-family: var(--sans);
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink3);
  padding: 0 8px;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .fbar {
    flex-wrap: wrap;
  }
  .ffoot {
    font-size: 10px;
  }
  .fthumbs {
    display: none;
  }
}

/* The page is fetched from the archive's own image service, so it can fail where a local file
   could not. The frame says so in place of the sheet, and the citation underneath - shelfmark,
   repository, record link - stays on screen, because it is still good when the image is not. */
.fstage.failed #facsImg {
  display: none;
}
.fstage.failed::after {
  content: "This page could not be fetched from the archive. Please access it directly from the record link below.";
  display: block;
  max-width: 34ch;
  margin: auto;
  font-family: var(--sans);
  font-size: 12px;
  line-height: 1.6;
  text-align: center;
  color: var(--ink3);
  border: 1px dashed var(--rule2);
  border-radius: 6px;
  padding: 20px 24px;
}
.chip.doc {
  color: var(--ink2);
  background: var(--paper3);
  font-weight: 400;
}
.chip.doc.seen {
  color: var(--ok);
  background: var(--ok-bg);
  font-weight: 600;
}
.chip.doc {
  cursor: pointer;
  border: 1px solid transparent;
}
.chip.doc:hover {
  border-color: var(--rule2);
  color: var(--ink);
}
.chip.doc.seen:hover {
  border-color: var(--ok);
  color: var(--ok);
}
.chip.doc[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
}
.chip.doc.seen[aria-pressed="true"] {
  color: var(--ok);
  border-color: var(--accent);
}

/* What was seen at the document itself, kept apart from where the passage was read in print.
   Running them together as one note is what let a PDF page number stand for a manuscript. */
.qcard .qorig {
  margin: 7px 0 0;
  padding-left: 9px;
  border-left: 2px solid var(--rule2);
  line-height: 1.5;
}
.qcard .qorig b {
  color: var(--ink2);
  font-weight: 600;
}
.qcard .qmarks {
  color: var(--ok);
}

/* The location chip is a button like the document chip, and shares its quiet-until-approached
   manner. It keeps the `how` chip's colour because it is a note about the source, not a claim. */
.chip.loc {
  cursor: pointer;
  border: 1px solid transparent;
  color: var(--ink2);
  background: var(--paper3);
  font-weight: 400;
}
.chip.loc:hover {
  border-color: var(--rule2);
  color: var(--ink);
}
.chip.loc[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
}
.chip.loc a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--rule2);
}
.chip.loc a:hover {
  border-bottom-color: var(--accent);
}

/* The two groups in the one filter box. A rule rather than a gap: soloing works within a group,
   so where one ends and the other begins has to be legible, not merely felt. */
.sfdocgroup {
  border-top: 1px solid var(--rule2);
  margin-top: 5px;
  padding-top: 5px;
}

/* ---- the letter reader -----------------------------------------------------------------------
   A card shows the letter among its apparatus - chips, commentary, the connection it was cited
   for; this shows it as a document, headed and set to a measure. It borrows the manuscript
   reader's bar and its opaque ground - a page of prose needs the panel behind it gone as much as
   a page of handwriting does - but it scrolls text rather than framing an image, so the stage is
   a reading column and not a stage at all. */
#letter {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: #100e0b;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}
#letter[hidden] {
  display: none;
}
.lstage {
  overflow-y: auto;
  padding: 26px 18px 64px;
}
.ltext,
.lnote {
  /* A measure, not a width: the letters run to a page or two and read as prose. */
  max-width: 34rem;
  margin: 0 auto;
}
.ltext {
  font-family: var(--serif, Georgia, "Times New Roman", serif);
  font-size: 1.02rem;
  line-height: 1.62;
  color: var(--ink, #e8e2d6);
}
.ltext p {
  margin: 0 0 0.85em;
}
/* The quoted passage, marked inside the whole letter. Deliberately an underlay rather than a
   highlighter: the point is to show where the card's excerpt sits and, by what is left unmarked
   between the runs, what the ellipsis dropped - not to shout. */
/* NO UNDERLINE, and not as a matter of taste: on this map an underline is Wilde's own emphasis,
   the thing `_underline_` renders and the reason the manuscripts were read at all. A decorative
   rule under the quoted passage competes with the one mark the reader is here to trust. The tint
   alone carries it, a little stronger now that it works unaided. */
/* An enclosure - a poem copied into a letter, a letter quoted inside another - set as a
   quotation within the quotation. Indented and ruled rather than italicised: the italics on
   this map are Wilde's own emphasis and cannot be spent on structure. */
.ltext blockquote.encl {
  margin: 0 0 0.85em 0.2em;
  padding-left: 0.9em;
  border-left: 2px solid var(--rule2);
  color: var(--ink2);
}
.ltext blockquote.encl p {
  margin: 0 0 0.35em;
}
.ltext blockquote.encl p:last-child {
  margin-bottom: 0;
}
/* A blank line inside a poem is its stanza break: it carries no words, so it needs a height
   of its own or the two stanzas close up. */
.ltext blockquote.encl p:empty {
  height: 0.5em;
}
.qcard blockquote .encl {
  display: block;
  margin: 0.35em 0;
  padding-left: 0.85em;
  border-left: 2px solid var(--rule2);
  color: var(--ink2);
}
/* Set out as the document set it: a bill in columns, a ledger, a sum. Monospaced so the
   columns line up, and scrollable on its own so a wide table cannot widen the letter. */
.ltext pre.setout,
.qcard blockquote .setout {
  display: block;
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Consolas, monospace);
  font-size: 0.86em;
  line-height: 1.5;
  white-space: pre;
  overflow-x: auto;
  margin: 0 0 0.85em;
  padding: 0.6em 0.8em;
  border-left: 2px solid var(--rule2);
  color: var(--ink2);
}
.ltext code,
.qcard code,
.qtrans code {
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Consolas, monospace);
  font-size: 0.9em;
}
/* The English for a word of another language standing inside an English letter, set beside it.
   Upright and quieter than the text, and never italic even where the phrase it follows is, so
   that it reads as the editor's word rather than as more of the writer's. */
/* The editor's English beside a phrase the writer left in another language. It wraps like the
   prose it sits in: it was `nowrap`, which keeps a two-word gloss whole but sends a long one
   straight through the right margin and puts a horizontal scrollbar under the letter - the
   French Wilde dictates to Sherard in 504#1 glosses to forty words. A gloss breaking across a
   line is what print does; a letter that scrolls sideways is not. */
.gloss {
  font-style: italic;
  color: var(--ink3);
  padding-left: 0.25em;
}
/* Something the page sets in the middle of the measure rather than against the left margin -
   a printer's device, an ornament between one thing and the next. Centred and nothing else:
   the words are the page's own, so they are not marked as anybody's commentary. */
.ltext p.centred,
.qcard blockquote p.centred,
.qcard p.centred {
  text-align: center;
  margin: 0.9em 0;
}
/* The writer's own caption to a drawing - centred and a shade apart from the prose, the way
   a caption sits under a picture. */
.ltext p.caption,
.qcard blockquote p.caption {
  text-align: center;
  color: var(--ink2);
  font-size: 0.94em;
  margin: 0.2em 0 0.9em;
}
/* A drawing the writer made: the words are the transcriber's description of it, so they read
   as an editorial note rather than as the letter's own sentence. */
.ltext p.sketch,
.qcard blockquote p.sketch {
  text-align: center;
  font-style: italic;
  color: var(--ink3);
  margin: 0.6em 0 0.2em;
}
/* Something the text cannot carry, standing where the volume prints it - two bars of a trio.
   Braces are the pipeline's; brackets are what this edition's reader reads as supplied. */
.mk {
  font-style: italic;
  color: var(--ink3);
}
/* A genuine side-by-side setting - a poem beside its translation. Falls back to one column
   under the narrow panel, where two would be unreadable. */
.ltext .cols,
.qcard blockquote .cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1.4em;
  margin: 0 0 0.85em;
}
@media (max-width: 700px) {
  .ltext .cols,
  .qcard blockquote .cols {
    grid-template-columns: 1fr;
  }
}
.ltext mark {
  background: rgba(212, 168, 83, 0.22);
  color: inherit;
  border-radius: 2px;
  /* A shade of breathing room, so the tint reads as a band rather than as touching the words. */
  padding: 0.05em 0.08em;
  margin: 0 -0.08em;
}
.lnote {
  margin-top: 28px;
  padding-top: 14px;
  border-top: 1px solid rgba(232, 226, 214, 0.16);
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--dim, #a49c8c);
}
.lnote p {
  margin: 0 0 0.6em;
}
.lwhen {
  opacity: 0.72;
}
.lnote details {
  margin-top: 0.4em;
}
.lnote summary {
  cursor: pointer;
  color: var(--accent, #d4a853);
  opacity: 0.85;
}
.lnote details[open] summary {
  margin-bottom: 0.5em;
}

/* The letter reader's title is a sentence of context, not a filename, and its citation is a full
   short-cite rather than the "3 of 12" the manuscript bar carries. Stacked, so the sentence gets
   the width and the citation is not squeezed into a four-line column beside it. */
#letter .ftitle {
  display: block;
  flex: 1 1 auto;
}
#letter .lname {
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.45;
  color: var(--ink);
  display: block;
}
#letter .lwhen {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  letter-spacing: 0.03em;
  /* Not uppercased: this is a citation, and "p. 1044" set as "P. 1044" reads as a mistake. */
  opacity: 0.62;
}
/* A guard, not the fix: the first sentence is short by convention (62 characters on average here)
   but nothing enforces that, and one long one should not push the letter off the screen. */
#letter .lname {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
