/* Colours are defined once by role and used by name. No sampled hex values
   scattered through the rules — changing the paper colour should be one edit.
   Both themes are declared here; the page follows the reader's system setting
   rather than asking them to choose. */
:root {
  color-scheme: light dark;

  /* Red, white and blue, kept quiet. The ink is a deep navy rather than
     black, so every line of text carries the blue without anything being
     coloured in; red is reserved for what you can act on or what is marked
     (links, the section you are reading, Tier 1); navy carries structure
     (part and section headings, Tier 2). No flag, no stripes, no third
     colour competing with either. */
  --paper: #fbfbf9;
  --paper-raised: #ffffff;
  --rule: #dfe1e6;
  --rule-strong: #c2c7d0;
  --ink: #101a33;
  --ink-soft: #44506b;
  --ink-faint: #737e96;
  --accent: #8c1d24;
  --accent-soft: #f4e8e8;
  --navy: #1b3a63;
  --tier1: #8c1d24;
  --tier2: #1b3a63;
  --focus: #1b3a63;
  /* The environment band stays outside the palette on purpose: it is a
     warning, and a warning that matches the design stops being one. */
  --warn-bg: #8a3d10;
  --warn-ink: #fff6ee;

  --measure: 44rem;
  --nav-width: 20rem;
  --topbar-height: 3.5rem;
  /* The environment band's height, named once. The top bar and the contents
     drawer both stick below it, and when this was a number repeated in three
     places they disagreed and the band overlapped the bar on any scrolled
     page. */
  --banner-height: 1.8rem;

  --font-body: ui-serif, Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  --font-ui: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0d1424;
    --paper-raised: #141d31;
    --rule: #24304a;
    --rule-strong: #3a4763;
    --ink: #e6ebf5;
    --ink-soft: #aab6cd;
    --ink-faint: #7e8aa3;
    --accent: #e79aa0;
    --accent-soft: #2b1c22;
    --navy: #8fb4e0;
    --tier1: #e79aa0;
    --tier2: #8fb4e0;
    --focus: #8fb4e0;
    --warn-bg: #c1601f;
    --warn-ink: #1a1207;
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-text-size-adjust: 100%;
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: #fff;
  padding: 0.6rem 1rem;
  z-index: 60;
}
.skip-link:focus {
  left: 0;
}

/* The environment label required by the standards. It is a band across the
   top of every page, not a hostname or a tab title, so it stays visible the
   whole time the site is being used. The Worker injects it; production never
   receives one. */
.env-banner {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--warn-bg);
  color: var(--warn-ink);
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-align: center;
  /* Exactly --banner-height, so what sticks below it lines up. */
  height: var(--banner-height);
  line-height: var(--banner-height);
  padding: 0 1rem;
  overflow: hidden;
  text-transform: uppercase;
}

/* Shown only in the cookie-refused fallback view. Deliberately NOT sticky:
   `.env-banner ~ .topbar` above offsets the bar by exactly one band height,
   and a second sticky band would slide the bar under it on the test site.
   This view is a single page load with the band at the top of it, so a band
   that scrolls with the page is enough and cannot misplace anything. */
.cookieless-banner {
  background: var(--warn-bg);
  color: var(--warn-ink);
  font-family: var(--font-ui);
  font-size: 0.8rem;
  line-height: 1.45;
  padding: 0.7rem 1rem;
  text-align: center;
}

.topbar {
  position: relative;
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  height: var(--topbar-height);
  padding: 0 0.9rem;
  background: var(--paper-raised);
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-ui);
}
/* The only ornament in the design: a two-pixel rule under the header running
   navy to red. Enough to place the thing without drawing a flag. */
.topbar::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: linear-gradient(to right, var(--navy), var(--accent));
  opacity: 0.85;
}

/* `~`, not `+`: the skip link sits between the band and the bar, so the
   adjacent-sibling selector never matched and the bar stuck to the top of the
   window underneath the band on every scrolled page. */
.env-banner ~ .topbar {
  top: var(--banner-height);
}

.topbar-title {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.topbar-name {
  font-size: 0.95rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.topbar-sub {
  font-size: 0.72rem;
  color: var(--ink-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

button,
input[type='submit'] {
  font: inherit;
  font-family: var(--font-ui);
  cursor: pointer;
}

.nav-toggle,
.home,
.admin-link,
.signout button {
  min-height: 2.5rem;
  padding: 0 0.85rem;
  border: 1px solid var(--rule-strong);
  border-radius: 0.4rem;
  background: transparent;
  color: var(--ink-soft);
  font-size: 0.85rem;
  white-space: nowrap;
}
.admin-link {
  display: flex;
  align-items: center;
  text-decoration: none;
}
.nav-toggle:hover,
.home:hover:not(:disabled),
.admin-link:hover,
.signout button:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.signout {
  margin: 0;
}

/* Prev/Next: icon-only everywhere, not just on a phone. They are new, so —
   unlike Contents/Home/Admin/Sign out, which already had a text-label design
   to preserve — there was no existing shape to match, and a fixed square is
   the one that stays cheap on width at every size, which the topbar has
   never had much of to spare (see the phone rules below). */
.prev,
.next {
  min-height: 2.5rem;
  min-width: 2.5rem;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--rule-strong);
  border-radius: 0.4rem;
  background: transparent;
  color: var(--ink-soft);
  font-size: 1.15rem;
  line-height: 1;
}
.prev:hover:not(:disabled),
.next:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
.home:disabled,
.prev:disabled,
.next:disabled {
  opacity: 0.35;
  cursor: default;
}

.shell {
  display: flex;
  align-items: flex-start;
}

.nav {
  width: var(--nav-width);
  flex: 0 0 var(--nav-width);
  position: sticky;
  top: var(--topbar-height);
  height: calc(100vh - var(--topbar-height));
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--rule);
  background: var(--paper-raised);
  font-family: var(--font-ui);
}

/* Same correction as the top bar: where there is an environment band, the
   drawer sticks below both it and the bar, not just the bar. Without this the
   search box sat underneath the bar on the test site. Production has no band,
   so this rule simply never applies there. */
.env-banner ~ .shell .nav {
  top: calc(var(--topbar-height) + var(--banner-height));
  height: calc(100vh - var(--topbar-height) - var(--banner-height));
}

.search {
  padding: 0.75rem;
  border-bottom: 1px solid var(--rule);
}
.search input {
  width: 100%;
  min-height: 2.5rem;
  padding: 0 0.7rem;
  font: inherit;
  font-size: 0.9rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  border-radius: 0.4rem;
}
.search-status {
  margin: 0.4rem 0 0;
  font-size: 0.75rem;
  color: var(--ink-faint);
  min-height: 1rem;
}

.nav-scroll {
  overflow-y: auto;
  padding: 0.5rem 0 3rem;
  flex: 1;
}

/* Fixed below the scrolling contents list rather than inside it — a version
   history is not a pillar and does not scroll away with them. `flex: 0 0
   auto` on a column flex parent (.nav) is what keeps it pinned to the
   bottom instead of growing with .nav-scroll's content. */
.nav-footer {
  flex: 0 0 auto;
  padding: 0.4rem;
  border-top: 1px solid var(--rule);
}
.nav-footer .nav-entry {
  border-radius: 0.4rem;
  padding-left: 0.9rem;
}

.nav-part-title {
  margin: 0.5rem 0 0;
}
.nav-part-toggle {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: transparent;
  color: var(--navy);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.7rem 0.9rem 0.7rem 1.6rem;
  position: relative;
}
.nav-part-toggle::before {
  content: '\25B8';
  position: absolute;
  left: 0.7rem;
  color: var(--ink-faint);
  display: inline-block;
  transition: transform 0.12s ease;
}
.nav-part-toggle[aria-expanded='true']::before {
  transform: rotate(90deg);
}
.nav-part-toggle:hover {
  color: var(--accent);
}
/* Closed by default. The script opens only the branch containing whatever is
   being read, so the list starts as five lines instead of several screens.
   Driven by a class on the section rather than by a sibling selector on the
   button: the button sits inside the `<h2>`, so `.nav-part-toggle + .nav-list`
   matches nothing — the same mistake that left the environment band sitting on
   top of the header. */
.nav-part > .nav-list {
  display: none;
}
.nav-part.is-open > .nav-list {
  display: block;
}

.nav-list,
.nav-group-items {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav-group-toggle {
  display: block;
  width: 100%;
  text-align: left;
  border: 0;
  background: transparent;
  color: var(--ink-soft);
  font-size: 0.82rem;
  font-weight: 600;
  padding: 0.55rem 0.9rem 0.55rem 1.6rem;
  position: relative;
}
.nav-group-toggle::before {
  content: '▸';
  position: absolute;
  left: 0.7rem;
  color: var(--ink-faint);
  transition: transform 0.12s ease;
  display: inline-block;
}
.nav-group-toggle[aria-expanded='true']::before {
  transform: rotate(90deg);
}
.nav-group-toggle:hover {
  color: var(--accent);
}
.nav-group-items {
  display: none;
}
.nav-group-toggle[aria-expanded='true'] + .nav-group-items {
  display: block;
}

.nav-entry {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.45rem 0.9rem 0.45rem 1.6rem;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.85rem;
  line-height: 1.35;
  min-height: 2.25rem;
}
.nav-entry:hover {
  background: var(--accent-soft);
  color: var(--accent);
}
.nav-entry[aria-current='true'] {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--accent);
}
.nav-number {
  flex: 0 0 1.6rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  font-size: 0.78rem;
}
.nav-text {
  flex: 1;
}
.nav-tier {
  flex: 0 0 auto;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--tier1);
  border: 1px solid currentColor;
  border-radius: 0.25rem;
  padding: 0 0.25rem;
  line-height: 1.4;
}
.nav-entry[hidden] {
  display: none;
}

.nav-item {
  list-style: none;
}
.nav-item[hidden] {
  display: none;
}

/* How many sub-sections a pillar has. A number rather than a caret, because
   it says something useful before you open it. */
.nav-count {
  flex: 0 0 auto;
  font-size: 0.62rem;
  color: var(--ink-faint);
  border: 1px solid var(--rule-strong);
  border-radius: 0.25rem;
  padding: 0 0.25rem;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
}

/* Every sub-section is in the markup so the search can read it and a link can
   be followed — but only the pillar being read shows its own, because 86 of
   them open at once is a wall rather than a contents list. */
.nav-subs {
  display: none;
  list-style: none;
  margin: 0 0 0.35rem;
  padding: 0;
}
.nav-item.is-current .nav-subs {
  display: block;
}
.nav-sub {
  display: block;
  padding: 0.35rem 0.9rem 0.35rem 3.1rem;
  position: relative;
  color: var(--ink-faint);
  text-decoration: none;
  font-size: 0.78rem;
  line-height: 1.35;
  min-height: 1.9rem;
}
.nav-sub::before {
  content: '';
  position: absolute;
  left: 2.35rem;
  top: 0.85rem;
  width: 0.4rem;
  height: 1px;
  background: var(--rule-strong);
}
.nav-sub:hover {
  color: var(--accent);
  background: var(--accent-soft);
}
.nav-sub[aria-current='true'] {
  color: var(--accent);
  font-weight: 600;
}

.reader {
  flex: 1;
  min-width: 0;
  padding: 2.5rem clamp(1rem, 5vw, 4rem) 6rem;
}
.reader:focus {
  outline: none;
}

.entry {
  max-width: var(--measure);
  margin: 0 auto;
}
.entry[hidden] {
  display: none;
}

.eyebrow {
  margin: 0 0 0.4rem;
  font-family: var(--font-ui);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.entry-title {
  margin: 0 0 0.6rem;
  font-size: clamp(1.6rem, 4.5vw, 2.2rem);
  line-height: 1.2;
  font-weight: 600;
}
.entry-number {
  display: block;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.3rem;
}
.eyebrow {
  color: var(--navy);
}

.badges {
  margin: 0 0 1.5rem;
}
.badge {
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 1px solid currentColor;
  border-radius: 0.25rem;
  padding: 0.15rem 0.45rem;
}
.badge-tier-1 {
  color: var(--tier1);
}
.badge-tier-2 {
  color: var(--tier2);
}

.prose > *:first-child {
  margin-top: 0;
}
.prose p,
.prose li {
  overflow-wrap: break-word;
}
.prose h2 {
  font-size: 1.25rem;
  margin: 2.2rem 0 0.6rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--rule);
}
/* A sub-section of a pillar. Given a little more presence than an ordinary
   heading because it is a link target — you arrive here from the index, and
   it should be obvious you landed in the right place. */
.prose h2.subhead {
  font-size: 1.3rem;
  margin-top: 2.6rem;
  padding-bottom: 0.4rem;
  border-bottom: 2px solid var(--rule-strong);
  /* Clears the sticky bar (and the band, where there is one) so an anchor
     lands below them rather than underneath. */
  scroll-margin-top: calc(var(--topbar-height) + var(--banner-height) + 1rem);
  color: var(--ink);
}
.prose h3 {
  font-size: 1.05rem;
  margin: 1.8rem 0 0.5rem;
}
.prose strong {
  color: var(--ink);
}
.prose em {
  color: var(--ink-soft);
}
.prose a {
  color: var(--accent);
}
.prose blockquote {
  margin: 1.2rem 0;
  padding: 0.6rem 1rem;
  border-left: 3px solid var(--rule-strong);
  background: var(--paper-raised);
  color: var(--ink-soft);
}
.prose blockquote p:first-child {
  margin-top: 0;
}
.prose blockquote p:last-child {
  margin-bottom: 0;
}
.prose hr {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 2rem 0;
}
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 0.25rem;
  padding: 0.05em 0.3em;
}
.prose pre {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  padding: 0.9rem;
  overflow-x: auto;
}
.prose pre code {
  border: 0;
  background: none;
  padding: 0;
}
/* Wide content scrolls inside its own box. The page body never scrolls
   sideways. */
.prose table {
  display: block;
  overflow-x: auto;
  border-collapse: collapse;
  width: 100%;
  font-family: var(--font-ui);
  font-size: 0.85rem;
}
.prose th,
.prose td {
  border: 1px solid var(--rule);
  padding: 0.4rem 0.6rem;
  text-align: left;
  vertical-align: top;
}
.prose th {
  background: var(--paper-raised);
}

/* The summary on the entry the site opens on. Counted at build time from the
   source, so it is a view of the document rather than a second copy of it. */
.glance {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font-family: var(--font-ui);
}
.glance h2 {
  margin: 0 0 1rem;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.glance-counts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 0.75rem;
  margin: 0 0 1.75rem;
}
.glance-counts div {
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  padding: 0.7rem 0.8rem;
  background: var(--paper-raised);
}
.glance-counts dt {
  font-size: 0.72rem;
  color: var(--ink-faint);
  line-height: 1.3;
}
.glance-counts dd {
  margin: 0.25rem 0 0;
  font-size: 1.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.glance-parts {
  list-style: none;
  margin: 0;
  padding: 0;
}
.glance-parts li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.88rem;
}
.glance-parts a {
  color: var(--accent);
}
.glance-note {
  margin: 1rem 0 0;
  font-size: 0.75rem;
  color: var(--ink-faint);
}
.glance-count {
  flex: 0 0 auto;
  color: var(--ink-faint);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}

/* The whole document as one clickable index, on the page it opens on.
   Every level closed to begin with: the point is not scrolling past every
   section to reach the one you want. */
.index {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font-family: var(--font-ui);
}
.index h2 {
  margin: 0 0 0.4rem;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.index-note {
  margin: 0 0 1rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.index-search {
  margin-bottom: 1.5rem;
}
.index-search input {
  width: 100%;
  min-height: 2.75rem;
  padding: 0 0.75rem;
  font: inherit;
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule-strong);
  border-radius: 0.4rem;
}
.index-status {
  margin: 0.4rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
  min-height: 1rem;
}

.index-part,
.index-group {
  border-top: 1px solid var(--rule);
}
.index-part[hidden],
.index-group[hidden],
.index-item[hidden] {
  display: none;
}
.index-part-title,
.index-section {
  margin: 0;
}

/* One button style for both levels; the part is the louder of the two. */
.index-toggle {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  min-height: 2.9rem;
  padding: 0.6rem 0.25rem 0.6rem 1.5rem;
  border: 0;
  background: transparent;
  text-align: left;
  position: relative;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  line-height: 1.3;
}
.index-toggle-part {
  color: var(--navy);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
}
.index-toggle::before {
  content: '\25B8';
  position: absolute;
  left: 0.35rem;
  color: var(--ink-faint);
  font-size: 0.85rem;
  transition: transform 0.12s ease;
  display: inline-block;
}
.index-toggle[aria-expanded='true']::before {
  transform: rotate(90deg);
}
.index-toggle:hover {
  color: var(--accent);
}
.index-count {
  margin-left: auto;
  flex: 0 0 auto;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--ink-faint);
  border: 1px solid var(--rule-strong);
  border-radius: 0.25rem;
  padding: 0 0.3rem;
  font-variant-numeric: tabular-nums;
}

.index-part-body,
.index-group > .index-entries {
  display: none;
}
.index-part.is-open > .index-part-body,
.index-group.is-open > .index-entries {
  display: block;
}

.index-entries {
  list-style: none;
  margin: 0;
  padding: 0 0 0.4rem;
}
.index-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  border-top: 1px solid var(--rule);
}
.index-entry {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  flex: 1;
  min-width: 0;
  padding: 0.55rem 0 0.55rem 1.5rem;
  color: var(--ink);
  text-decoration: none;
  font-size: 0.9rem;
  line-height: 1.35;
  min-height: 2.4rem;
}
.index-entry:hover {
  color: var(--accent);
}
.index-num {
  flex: 0 0 1.7rem;
  color: var(--ink-faint);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}
.index-label {
  flex: 1;
  min-width: 0;
}
.index-tier {
  flex: 0 0 auto;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tier1);
  border: 1px solid currentColor;
  border-radius: 0.25rem;
  padding: 0 0.3rem;
  white-space: nowrap;
}

/* How many sub-sections a pillar has, and the control that opens them. A
   number rather than a caret: it says something useful before you tap it. */
.index-subs-toggle {
  flex: 0 0 auto;
  min-width: 2.4rem;
  min-height: 2.4rem;
  margin-left: 0.5rem;
  border: 1px solid var(--rule-strong);
  border-radius: 0.3rem;
  background: transparent;
  color: var(--ink-faint);
  font-family: var(--font-ui);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}
.index-subs-toggle:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.index-subs-toggle[aria-expanded='true'] {
  border-color: var(--accent);
  color: var(--accent);
}

.index-subs {
  display: none;
  list-style: none;
  flex: 0 0 100%;
  margin: 0 0 0.5rem;
  padding: 0 0 0 3.2rem;
}
.index-item.is-open .index-subs {
  display: block;
}
.index-subs li[hidden] {
  display: none;
}
.index-subs a {
  display: block;
  position: relative;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.85rem;
  line-height: 1.4;
  padding: 0.45rem 0;
  min-height: 2.1rem;
}
.index-subs a::before {
  content: '';
  position: absolute;
  left: -0.9rem;
  top: 1.05rem;
  width: 0.45rem;
  height: 1px;
  background: var(--rule-strong);
}
.index-subs a:hover {
  color: var(--accent);
}

mark {
  background: var(--accent-soft);
  color: inherit;
  box-shadow: 0 1px 0 var(--accent);
}

/* ---- Sign-in and first-login pages -------------------------------------- */

.auth {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 1rem 4rem;
}
.auth-card {
  width: 100%;
  max-width: 26rem;
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: 0.6rem;
  padding: 1.75rem;
}
.auth-card h1 {
  margin: 0 0 0.25rem;
  font-size: 1.5rem;
  line-height: 1.2;
}
.auth-card .lede {
  margin: 0 0 1.5rem;
  color: var(--ink-soft);
  font-size: 0.95rem;
}
.field {
  display: block;
  margin-bottom: 1rem;
}
.field span {
  display: block;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 0.3rem;
}
.field input {
  width: 100%;
  min-height: 2.75rem;
  padding: 0 0.75rem;
  font: inherit;
  font-family: var(--font-ui);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  border-radius: 0.4rem;
}
.auth button[type='submit'] {
  width: 100%;
  min-height: 2.85rem;
  border: 0;
  border-radius: 0.4rem;
  background: var(--accent);
  color: #fff;
  font-size: 0.95rem;
  font-weight: 600;
}
.notice {
  margin: 0 0 1.25rem;
  padding: 0.7rem 0.85rem;
  border-radius: 0.4rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  border: 1px solid var(--rule-strong);
  background: var(--paper);
  color: var(--ink-soft);
}
.notice-error {
  border-color: var(--accent);
  color: var(--accent);
}
.hint {
  /* Symmetric rather than top-only: every prior use was the last thing in
     its card, so a bottom margin never showed. The admin page's top
     "Back to the document" link is the first .hint to sit directly above
     something else (the invite form) rather than the bottom of the card,
     and margins between block siblings collapse to the larger side anyway,
     so this costs nothing where it already looked right. */
  margin: 1.25rem 0;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font-family: var(--font-ui);
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--ink-faint);
}
.rules {
  margin: 0 0 1.25rem;
  padding-left: 1.1rem;
  font-family: var(--font-ui);
  font-size: 0.82rem;
  color: var(--ink-faint);
}

/* ---- Admin --------------------------------------------------------------
   Reuses .auth-card's chrome (border, radius, padding) at a width a member
   table can actually sit in — see authPage()'s `wide` option. */
.auth-card-wide {
  max-width: 46rem;
}
.admin-section-heading {
  margin: 1.75rem 0 0.75rem;
  font-size: 1.05rem;
}
.admin-table-wrap {
  /* The table has four columns and an email column that does not wrap well;
     on a phone width that is wider than the card, so it scrolls in its own
     box instead of forcing the page itself wider than the viewport. */
  overflow-x: auto;
}
.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-ui);
  font-size: 0.85rem;
}
.admin-table th,
.admin-table td {
  text-align: left;
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--rule);
}
.admin-table th {
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.admin-table-empty {
  color: var(--ink-faint);
}
.revoke-form {
  display: flex;
  gap: 0.4rem;
  align-items: center;
}
.revoke-reason {
  width: 9rem;
  min-height: 2rem;
  padding: 0 0.5rem;
  font: inherit;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule-strong);
  border-radius: 0.35rem;
}
.revoke-button {
  min-height: 2rem;
  padding: 0 0.7rem;
  border: 1px solid var(--accent);
  border-radius: 0.35rem;
  background: transparent;
  color: var(--accent);
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

/* ---- Phone ------------------------------------------------------------- */

@media (max-width: 52rem) {
  /* The topbar routinely carries six controls on a phone width (Contents,
     Back, Prev, Next, Admin, Sign out) plus this title, and giving the title
     its usual share of the row left it a handful of pixels — enough for two
     or three characters of a name that is never that short, which is what
     produced "Pro…" / "Mast…" instead of anything legible. The current
     pillar heading is already the first thing in the reader below this bar,
     so the title earns its keep less here than the width it would need to
     stop truncating into noise. */
  .topbar-title {
    display: none;
  }
  .topbar {
    gap: 0.35rem;
    padding: 0 0.5rem;
  }
  /* Contents is the widest label in the bar and the one every reader has
     already seen spelled out once by the time the screen is this narrow, so
     it is the one that goes icon-only rather than splitting the saving
     thinly across all four text buttons. ☰ is not part of this design's
     otherwise-geometric-arrow vocabulary (← → ‹ ›), but it is the one glyph
     every reader already recognises as "open the menu" independent of that. */
  .nav-toggle .btn-label {
    display: none;
  }
  .nav-toggle {
    min-width: 2.5rem;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.1rem;
  }
  .home,
  .admin-link,
  .signout button {
    padding: 0 0.5rem;
  }
  .nav {
    position: fixed;
    inset: var(--topbar-height) auto 0 0;
    width: min(88vw, var(--nav-width));
    height: calc(100dvh - var(--topbar-height));
    z-index: 45;
    transform: translateX(-100%);
    transition: transform 0.16s ease;
    box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0);
  }
  .env-banner ~ .shell .nav {
    top: calc(var(--topbar-height) + var(--banner-height));
    height: calc(100dvh - var(--topbar-height) - var(--banner-height));
  }
  body.nav-open .nav {
    transform: translateX(0);
    box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.35);
  }
  .reader {
    padding: 1.5rem 1.1rem 5rem;
  }
}

@media (min-width: 52.0625rem) {
  .nav-toggle {
    display: none;
  }
}
