:root {
  /* Polaris design framework v1.1. Bricolage Grotesque where the page speaks
     as a heading, Instrument Sans everywhere else, IBM Plex Mono for data.

     `--reader` is Instrument Sans too. The framework admits no serif face, and
     the spec text is not an exception to it: a document read for an hour at a
     time is read in the family the rest of the surface is set in. */
  --mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --display: "Bricolage Grotesque", system-ui, -apple-system, sans-serif;
  --ui: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --reader: var(--ui);

  /* The chrome's two heights, stated once. `.app-shell` subtracts both to fill
     what is left, and got them wrong the moment a footer appeared under a
     hardcoded `calc(100vh - 54px)`. */
  --header-height: 54px;
  --footer-height: 30px;
  /* What the menu leaves behind when it folds: enough for the button that
     brings it back, and nothing else. */
  --sidebar-rail: 40px;
  /* The sidebar's own header and each document panel's publisher row sit side
     by side, so their bottom rules have to fall on the same line: one token,
     not two paddings kept in sync by hand. */
  --panel-header-height: 54px;
}

/* The framework's core tokens, written into the roles this reader already had.
   --paper, --ink, --olive, --olive-deep, --chartreuse and --gold are the six;
   --neutral and --fail are two of the four functional colours. Every value that
   carries text was checked to clear 4.5:1 on the ground it sits on, which is
   why --faint is darker here than the framework's --neutral: --neutral labels a
   status beside a word, it does not set small text. */
body[data-palette="daylight"] {
  --chrome: #E9E6D7;
  --chrome-deep: #DFDCCA;
  --paper: #F1EFE3;
  /* The document's own reading surface, lighter than --paper: the user's explicit
     choice over the framework's --paper for the text a reader spends an hour on.
     The text area only (.document-body); the header rows above it keep --paper. */
  --reading: #F8F7F0;
  --ink: #23281B;
  --muted: #5C6B3C;
  --faint: #676C58;
  --line: #C6C4B0;
  --line-light: #DCD9C7;
  /* Accented text is olive-deep, never chartreuse: the framework forbids
     chartreuse as a text colour, and gives it the energy roles instead --
     active states, focus, rules, selected rows. */
  --accent: #333D22;
  --energy: #B7C94B;
  --accent-soft: #E6EAC8;
  --on-accent: #F1EFE3;
  --adjacent-mark: #C9A227;
  --gap-soft: #F0E3D6;
  --fail: #A0522D;
  /* No drop shadows. Structure is drawn with 1px rules and whitespace. */
  --shadow: transparent;

  /* One colour per behaviour, deep enough to read as a wash over cream paper. */
  --hue-1: 74 83 179;
  --hue-2: 176 84 48;
  --hue-3: 31 116 110;
  --hue-4: 160 110 20;
  --hue-5: 129 62 129;
  --hue-6: 95 122 47;
  --hue-7: 62 106 158;
  --hue-8: 165 56 74;
  --hue-9: 123 96 45;
  --hue-10: 44 128 150;
  --hue-11: 44 106 74;
  --hue-12: 146 92 116;

  /* How much of that colour a passage carries: core at full strength, related thinned,
     -strong for the passage the reader is standing on. */
  --tint-core: .21;
  --tint-related: .085;
  --tint-core-strong: .34;
  --tint-related-strong: .19;
  --rule-core: .85;
  --rule-related: .38;

}

/* The framework's dark surface: --olive-deep as the ground, --paper as the
   text, the same accents. The name stays "umber" because it is what the URL and
   the stored preference say; the ground is olive now. */
body[data-palette="umber"] {
  --chrome: #2A331C;
  --chrome-deep: #323C23;
  --paper: #333D22;
  /* Unchanged on the dark surface: the reading surface is the ground itself. */
  --reading: #333D22;
  --ink: #F1EFE3;
  --muted: #C4CBA8;
  --faint: #A2AA88;
  --line: #4A552F;
  --line-light: #3E4827;
  /* Olive lifted until it clears 4.5:1 on the olive-deep ground. Light enough
     that what sits *on* it must be dark: hence `--on-accent`. */
  --accent: #C7D69A;
  --energy: #B7C94B;
  --accent-soft: #46522A;
  --on-accent: #23281B;
  --adjacent-mark: #D9B93F;
  --gap-soft: #4A3020;
  --fail: #C97A4D;
  --shadow: transparent;

  /* The same twelve, lifted so they read as light laid on a dark surface. */
  --hue-1: 139 148 236;
  --hue-2: 226 141 100;
  --hue-3: 106 196 186;
  --hue-4: 224 179 82;
  --hue-5: 206 145 206;
  --hue-6: 170 197 110;
  --hue-7: 130 175 226;
  --hue-8: 230 130 146;
  --hue-9: 205 176 116;
  --hue-10: 120 200 220;
  --hue-11: 120 200 160;
  --hue-12: 220 160 185;

  --tint-core: .22;
  --tint-related: .095;
  --tint-core-strong: .34;
  --tint-related-strong: .2;
  --rule-core: .9;
  --rule-related: .4;

}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--chrome);
  color: var(--ink);
  font-family: var(--ui);
  /* 14px, not the 15px this carried under EB Garamond. Inter has much the
     larger x-height: kept at 15 it reads a size bigger and the sidebar, which
     is dense and fixed-width, stops fitting. */
  font-size: 14px;
  overflow: hidden;
}

button, a { -webkit-tap-highlight-color: transparent; }
button { font: inherit; }

.skip-link {
  position: fixed;
  z-index: 100;
  top: 8px;
  left: 8px;
  padding: 9px 13px;
  background: var(--ink);
  /* Not `white`: `--ink` is the cream #EDE5D3 under the umber palette, and the
     link — the one affordance a keyboard user meets first — was white on it. */
  color: var(--chrome);
  transform: translateY(-150%);
}

.skip-link:focus { transform: none; }

.site-header {
  height: var(--header-height);
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--line);
  background: var(--chrome);
}

/* Aligned on the baseline, not on the boxes. The wordmark is small-caps at
   16px and the collective's name ordinary text at 15px: centred, their boxes
   line up while their letters do not, and the wordmark rides visibly low. The
   star and the rule are not text and keep to the centre. */
.site-brand {
  display: flex;
  align-items: baseline;
  gap: 10px;
  /* The mark and the name take one pair of tones and move together, as they do
     in the bar of evals-playground: olive at rest, olive-deep under the
     pointer, ink while pressed. On the umber surface there is nothing darker
     than the ground to move to, so the pair brightens to paper instead. */
  --brand-rest: var(--muted);
  --brand-lit: var(--accent);
  --brand-pressed: var(--ink);
}

body[data-palette="umber"] .site-brand {
  --brand-lit: var(--ink);
  --brand-pressed: var(--ink);
}

/* The broken orbit, the collective's one mark. It carries the accent while the
   wordmark keeps the ink: the mark says whose site this is, the wordmark says
   what it is. It appears here, in the footer and in the icons, nowhere else. */
.polaris-mark {
  width: 20px;
  height: 20px;
  flex: none;
  /* Olive, not the olive-deep the framework gives the mark on paper: at 20px
     the deep tone reads as a smudge beside its name. The darkening that tone
     would have been is spent on hover instead. */
  color: var(--brand-rest);
  transition: color .15s ease;
}

/* The mark leaves for polariscollective.org, the same place its name leaves
   for. It is a second link to one destination, so it is kept out of the
   reading order and out of the tab order: the name beside it is the one link
   a keyboard or a screen reader meets. */
.mark-link {
  display: flex;
  flex: none;
  align-self: center;
}

/* The mark, the collective's name, a rule, then what the site is: the same
   pieces in the same order as the bar of evals-playground, leaving for the
   same place, polariscollective.org. */
.collective {
  color: var(--brand-rest);
  text-decoration: none;
  font-family: var(--display);
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  transition: color .15s ease;
}

/* Mark and name are one target and answer as one: whichever half the pointer
   is over, both darken. The framework's chartreuse highlight is for links in
   prose, and is not used here: it would fill a block behind the name that the
   mark beside it cannot take, and the two halves of one lockup would answer
   the pointer differently. The name of the collective darkens, the bar it sits
   in does not move. */
.mark-link:hover .polaris-mark,
.site-brand:has(.collective:hover) .polaris-mark,
.mark-link:hover + .collective,
.collective:hover {
  color: var(--brand-lit);
}

.mark-link:active .polaris-mark,
.site-brand:has(.collective:active) .polaris-mark,
.mark-link:active + .collective,
.collective:active {
  color: var(--brand-pressed);
}

.brand-divider {
  width: 1px;
  height: 15px;
  flex: none;
  align-self: center;
  background: var(--line);
}

.wordmark {
  font-family: var(--display);
  color: var(--ink);
  text-decoration: none;
  font-size: 17px;
  font-weight: 600;
}

.site-header nav { display: flex; align-items: center; gap: 24px; }
.site-header nav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 14px;
}
.site-header nav a:hover { background: var(--energy); color: var(--ink); }
/* The page you are on carries the chartreuse rule under it. */
.site-header nav a.active {
  color: var(--ink);
  box-shadow: inset 0 -2px 0 var(--energy);
}
.mode {
  padding: 4px 6px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 16px;
  cursor: pointer;
}
.mode:hover { background: var(--energy); color: var(--ink); }

.app-shell {
  --sidebar-width: 292px;
  height: calc(100vh - var(--header-height) - var(--footer-height));
  display: grid;
  grid-template-columns: var(--sidebar-width) 9px minmax(0, 1fr);
}

/* Where the project came from, and who runs it now. One slim bar: this is a
   full-height application, and every pixel here is a pixel of spec text not
   shown. */
.site-footer {
  height: var(--footer-height);
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  border-top: 1px solid var(--line);
  background: var(--chrome);
  color: var(--faint);
  font-size: 12px;
}

.site-footer a {
  color: var(--muted);
  text-decoration: none;
}

.site-footer a:hover {
  background: var(--energy);
  color: var(--ink);
}

body.embedded .skip-link,
body.embedded .site-header,
body.embedded .site-footer,
body.embedded .sidebar-toggle,
body.embedded .behaviour-sidebar {
  display: none;
}

body.embedded .sidebar-resizer {
  display: none;
}

body.embedded .app-shell {
  height: 100vh;
  height: 100dvh;
  grid-template-columns: minmax(0, 1fr);
}


.behaviour-sidebar {
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--chrome);
}

.column-resizer {
  position: relative;
  z-index: 4;
  width: 9px;
  min-width: 9px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: col-resize;
  touch-action: none;
}
.column-resizer::before {
  content: "";
  position: absolute;
  inset: 0 4px;
  background: var(--line);
  transition: inset .15s ease, background-color .15s ease;
}
.column-resizer:hover::before,
.column-resizer:focus-visible::before,
.column-resizer.dragging::before {
  inset-right: 3px;
  inset-left: 3px;
  background: var(--energy);
}
.column-resizer::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 3px;
  height: 34px;
  border-top: 1px solid var(--paper);
  border-bottom: 1px solid var(--paper);
  opacity: 0;
  transform: translate(-50%, -50%);
}
.column-resizer:hover::after,
.column-resizer:focus-visible::after,
.column-resizer.dragging::after { opacity: .72; }
body.resizing-columns {
  cursor: col-resize;
  user-select: none;
}

/* The reader's name and nothing else. What this surface is for belongs in the
   note that sends a reviewer here, not standing over the menu they came to use --
   the sidebar's whole height is worth more as behaviours than as an explanation read once. */
.sidebar-intro {
  min-height: var(--panel-header-height);
  padding: 0 25px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 1px solid var(--line);
}
/* Was an eyebrow: small, tracked, upper-case. The framework has no eyebrows, so
   this is what it always was, a heading, said at heading size in sentence case. */
.eyebrow {
  margin: 0;
  color: var(--ink);
  font-family: var(--display);
  font-size: 15px;
  font-weight: 600;
}

.behaviour-toolbar {
  padding: 10px 25px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 1px solid var(--line-light);
  color: var(--muted);
  font-size: 11px;
}
.behaviour-toolbar[hidden] { display: none; }
.behaviour-toolbar-actions { display: inline-flex; gap: 4px; }
/* Secondary button: 1px olive border, ink text, transparent ground, pill. */
.behaviour-toolbar-actions button {
  padding: 3px 10px;
  border: 1px solid var(--muted);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-size: 11px;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.behaviour-toolbar-actions button:hover:not(:disabled) { background: var(--energy); color: var(--ink); }
.behaviour-toolbar-actions button:disabled { opacity: .4; cursor: default; }

.behaviour-list { flex: 1; min-height: 0; overflow: auto; padding: 8px 0 18px; }
.behaviour-group { border-bottom: 1px solid var(--line-light); }
/* A group's heading row: its name, and at the right the depth column's scale, said
   once here rather than beside every figure. The right padding lines the label up
   with the figures' right edge: the list's 10px, the note button's 18px and 8px
   margin, and the label's own 12px. */
.behaviour-group-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 15px 48px 7px 25px;
}
/* The scale is a control: it opens the rubric the figures are scored on. The
   padding is a hit area and the negative margins give it straight back, so the
   heading row is no taller for it and the label still ends where the figures
   below it end. */
.depth-head {
  flex: none;
  margin: -2px -5px;
  padding: 2px 5px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--faint);
  font-family: inherit;
  font-weight: inherit;
  font-size: 11px;
  line-height: 1.35;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.depth-head:hover,
.depth-head[aria-expanded="true"] { background: var(--energy); color: var(--ink); }
.behaviour-group h2 {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: 0;
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.35;
}
.behaviour-group ul { list-style: none; margin: 0; padding: 0 10px 10px; }
/* The row as it is drawn. The tick target and the depth figure sit in it side by
   side: the figure is a button, and a button inside a label would be ticked by
   the label on its way past, so the ground they share is this frame rather than
   the label it used to be. */
.behaviour-option-frame {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 34px;
  padding: 7px 12px 7px 12px;
  display: flex;
  gap: 9px;
  align-items: baseline;
  border-radius: 5px;
}
.behaviour-option {
  flex: 1;
  min-width: 0;
  position: relative;
  display: flex;
  gap: 9px;
  align-items: baseline;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
}
.behaviour-option-frame:hover { background: var(--chrome-deep); }
.behaviour-option-frame:has(.behaviour-option.checked) {
  background: var(--paper);
  box-shadow: inset 3px 0 0 rgb(var(--bh) / var(--rule-core));
}
.behaviour-check {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}
.behaviour-box {
  width: 13px;
  height: 13px;
  flex: none;
  align-self: center;
  border: 1px solid var(--muted);
  border-radius: 4px;
  background: var(--paper);
}
.behaviour-option-frame:hover .behaviour-box { border-color: rgb(var(--bh) / var(--rule-core)); }
.behaviour-option.checked .behaviour-box {
  position: relative;
  border-color: rgb(var(--bh) / var(--rule-core));
  background: rgb(var(--bh) / var(--rule-core));
}
.behaviour-option.checked .behaviour-box::after {
  content: "";
  position: absolute;
  top: 1px;
  left: 3.5px;
  width: 3px;
  height: 6px;
  border: solid var(--paper);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(42deg);
}
.behaviour-check:focus-visible + .behaviour-box {
  outline: 2px solid var(--energy);
  outline-offset: 2px;
}
/* A stippled group is marked in the menu as well as in the text: its heading rule and the
   selected row's spine are broken the same way the passage's margin rule is, so the group
   reads as a different kind of row before a spec is even open. */
.behaviour-group.texture-stipple h2 {
  display: flex;
  align-items: center;
  gap: 7px;
}
.behaviour-group.texture-stipple h2::after {
  content: "";
  height: 3px;
  flex: 1;
  border-radius: 2px;
  background-image: repeating-linear-gradient(
    to right, currentColor 0 3px, transparent 3px 6px);
  opacity: .45;
}
.behaviour-option-frame:has(.behaviour-option.texture-stipple.checked) {
  background-image: repeating-linear-gradient(
    to bottom, rgb(var(--bh) / var(--rule-core)) 0 3px, transparent 3px 6px);
  background-size: 3px 100%;
  background-position: 0 0;
  background-repeat: no-repeat;
  box-shadow: none;
}
.behaviour-option .number {
  width: 20px;
  flex: none;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.behaviour-option .name { flex: 1; font-size: 12px; line-height: 1.35; }
/* A behaviour's depth on the documents on screen: a figure, so mono, and quiet
   beside the name it qualifies. A control as well as a reading, which is where
   "why is this a 1" is answered; its padding and negative margins are a hit area
   that costs the row no height, the same trade the scale above it makes. */
.behaviour-option-row .depth {
  flex: none;
  margin: -2px -5px;
  padding: 2px 5px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--faint);
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.behaviour-option-row .depth:hover,
.behaviour-option-row .depth[aria-expanded="true"] {
  background: var(--energy);
  color: var(--ink);
}
/* Read by a screen reader, drawn for no one. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.behaviour-option.checked .name { color: var(--ink); }

/* The information control beside a behaviour. It sits outside the label, because
   the label is the tick target and a click inside it would tick the row. */
.behaviour-option-row {
  display: flex;
  align-items: center;
}
.behaviour-why {
  flex: none;
  width: 18px;
  height: 18px;
  margin-right: 8px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  color: var(--faint);
  font-family: var(--ui);
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.behaviour-why:hover,
.behaviour-why:focus-visible {
  border-color: transparent;
  background: var(--energy);
  color: var(--ink);
}

/* The first line of a behaviour note: defined or not, judged or not. Those are
   independent states and the note says both, because the menu shows every
   behaviour alike and gives a reader no way to tell them apart. */
.behaviour-note-state {
  margin: 0 0 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line-light);
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
}

/* Each judge's depth, under the paragraph naming a document's mean: quieter than
   the paragraph, marked the way a spec passage's own lists are marked, so the
   note does not invent a second bullet system. */
.behaviour-note-depth-judges {
  margin: -6px 0 10px;
  padding-left: 1.15em;
  list-style: none;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.5;
}
.behaviour-note-depth-judges li { position: relative; margin: .3em 0; }
.behaviour-note-depth-judges li::before {
  content: "";
  position: absolute;
  top: .55em;
  left: -.95em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--energy);
}

/* What the depth column opens: the scale from its heading, one cell from a
   figure. Built like the key's notes -- fixed, in the top layer, cornered from
   the control that opened it -- and bounded the same way, so a judge who wrote
   three hundred words scrolls inside the box instead of stretching the page. */
.depth-note {
  position: fixed;
  inset: auto;
  width: min(380px, calc(100vw - 32px));
  max-height: min(70vh, 520px);
  overflow: auto;
  padding: 16px 18px 18px;
  border: 1px solid var(--muted);
  border-radius: 4px;
  background: var(--paper);
  color: var(--ink);
}
.depth-note::backdrop { background: transparent; }
.depth-note:focus-visible { outline: 2px solid var(--energy); outline-offset: 2px; }

.depth-note-title {
  margin: 0 0 10px;
  font-family: var(--display);
  font-size: 17px;
  font-weight: 600;
}
.depth-note-body { font-size: 13px; line-height: 1.55; }
.depth-note-body p { margin: 0 0 10px; }

/* What depth is, and is not, before the levels it is read on. */
.depth-note-lede {
  display: block;
  margin: 0 0 12px;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--line-light);
  color: var(--muted);
}

/* The rubric's five levels, one row each: the figure and its anchor on the first
   line, the bar under them. Two columns rather than three, so the bar keeps its
   width at any window and the row never asks the page to scroll sideways. */
.depth-note-scale,
.depth-note-judges {
  margin: 0 0 4px;
  padding: 0;
  list-style: none;
}
.depth-note-scale li,
.depth-note-judges li {
  display: grid;
  gap: 2px 9px;
  padding: 9px 0;
  border-top: 1px solid var(--line-light);
}
.depth-note-scale li { grid-template-columns: 14px 1fr; }
.depth-note-scale li:first-child,
.depth-note-judges li:first-child { border-top: 0; padding-top: 2px; }
.depth-note-level {
  font-family: var(--mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.depth-note-anchor { color: var(--ink); font-weight: 600; }
.depth-note-bar,
.depth-note-rationale { grid-column: 2 / -1; color: var(--muted); }

/* Each document the figure covers, named over its own reading. The framework's
   section heading: a 56px chartreuse rule, the name under it. The rule is drawn
   rather than made of the heading's own box, so a long title wraps like prose
   instead of being held to 56px. */
.depth-note-body h3 {
  margin: 20px 0 7px;
  color: var(--accent);
  font-family: var(--display);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
}
.depth-note-body h3::before {
  content: "";
  display: block;
  width: 56px;
  height: 3px;
  margin-bottom: 9px;
  background: var(--energy);
}
.depth-note-body h3:first-child { margin-top: 0; }

/* The mean, with the figure in the data face and the rest of the sentence in
   the reading one. */
.depth-note-mean { color: var(--ink); }
.depth-note-figure {
  margin-right: 2px;
  font-family: var(--mono);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}
.depth-note-substitution { color: var(--muted); }

/* One judge: who, what it gave, and why. The name is a model identifier and the
   score is a figure, so both are mono; the rationale is prose and is not. */
.depth-note-judges li { grid-template-columns: 1fr auto; }
.depth-note-judge {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink);
}
.depth-note-score {
  font-family: var(--mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--accent);
}

/* The export sits at the foot of the menu rather than in the toolbar at its head: it acts on
   the ticked set, so it reads as the end of the list it takes away and not as a third control
   beside All and None. The line under it counts what would come out, so the reader knows what
   they are asking for before the file lands. */
.sidebar-export {
  padding: 12px 22px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  border-top: 1px solid var(--line);
}
/* Primary button: olive-deep ground, paper text, pill; chartreuse on hover with
   the text going to ink. */
.download-passages {
  width: 100%;
  padding: 8px 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 12px;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.download-passages:hover:not(:disabled) {
  background: var(--energy);
  color: var(--ink);
}
.download-passages:disabled { opacity: .4; cursor: default; }
.download-hint {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.4;
  text-align: center;
}

.sidebar-key {
  padding: 12px 22px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 13px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 11px;
}
/* Each entry opens a note saying what the mark means and what the judge was
   asked for it. Buttons rather than the spans they were: the thing is clickable
   and reachable by keyboard, and only a button says both. */
.key-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 4px;
  margin: -2px -4px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.key-item:hover { background: var(--chrome-deep); color: var(--ink); }
.key-item:focus-visible { outline: 2px solid var(--energy); outline-offset: 1px; }

/* The note. `position: fixed` with the corner set from the button it belongs to:
   a popover lands in the top layer, where the browser's own centring would put
   it in the middle of the window rather than beside what was clicked. */
.key-note {
  position: fixed;
  inset: auto;
  width: min(360px, calc(100vw - 32px));
  max-height: min(70vh, 520px);
  overflow: auto;
  padding: 16px 18px 18px;
  border: 1px solid var(--muted);
  border-radius: 4px;
  background: var(--paper);
  color: var(--ink);
}

.key-note::backdrop { background: transparent; }

.key-note-title {
  margin: 0 0 10px;
  font-family: var(--display);
  font-size: 17px;
  font-weight: 600;
}

.key-note-body { font-size: 13px; line-height: 1.55; }
.key-note-body p { margin: 0 0 10px; }
.key-note-body p:last-child { margin-bottom: 0; }

/* The two halves of every note: what the judge was asked, and what the reader
   draws from the answers. They are not the same thing, and the whole point of
   the note is that they are told apart. */
/* The framework's section heading: a short chartreuse rule above, the heading
   under it in sentence case. */
.key-note-body h3 {
  margin: 16px 0 5px;
  padding-top: 9px;
  border-top: 3px solid var(--energy);
  width: 56px;
  color: var(--accent);
  font-family: var(--display);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.key-note-body h3:first-child { margin-top: 0; }
.key-note-body em { color: var(--muted); font-style: italic; }
/* The key is painted the way a passage is: the margin rules on the right, the wash behind. */
.key-swatch {
  width: 16px;
  height: 10px;
  display: inline-block;
  border-radius: 2px;
  background:
    linear-gradient(to left, rgb(var(--hue-1) / var(--rule-core)) 0 2px, transparent 2px),
    linear-gradient(rgb(var(--hue-1) / var(--tint-core)), rgb(var(--hue-1) / var(--tint-core)));
}
/* Defining carries the widest margin rule, the same way .legend-mark.defining is the
   widest mark in the header: the tier the shipped 3-point data actually puts its
   passages in was missing from the key entirely. */
.key-swatch.defining {
  background:
    linear-gradient(to left, rgb(var(--hue-1) / var(--rule-core)) 0 4px, transparent 4px),
    linear-gradient(rgb(var(--hue-1) / var(--tint-core)), rgb(var(--hue-1) / var(--tint-core)));
}
.key-swatch.related {
  background:
    linear-gradient(to left, rgb(var(--hue-1) / var(--rule-related)) 0 2px, transparent 2px),
    linear-gradient(rgb(var(--hue-1) / var(--tint-related)), rgb(var(--hue-1) / var(--tint-related)));
}
.key-swatch.overlap {
  background:
    linear-gradient(to left,
      rgb(var(--hue-3) / var(--rule-core)) 0 2px,
      transparent 2px 3px,
      rgb(var(--hue-1) / var(--rule-core)) 3px 5px,
      transparent 5px),
    linear-gradient(100deg,
      rgb(var(--hue-1) / var(--tint-core)),
      rgb(var(--hue-3) / var(--tint-core)));
}
/* The group key: the same wash, with the margin rule broken instead of solid. */
.key-swatch.stipple {
  background:
    repeating-linear-gradient(to bottom,
      rgb(var(--hue-1) / var(--rule-core)) 0 3px,
      transparent 3px 6px) 100% 0 / 2px 100% no-repeat,
    linear-gradient(rgb(var(--hue-1) / var(--tint-core)), rgb(var(--hue-1) / var(--tint-core)));
}

.workspace { min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.compare-toggle {
  min-height: 34px;
  padding: 8px 14px;
  border: 1px solid var(--muted);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-size: 12px;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}

/* A link, not a button. It leaves the site for the publisher's own copy, which
   is what a link does; the pill it used to wear made it read as one of the
   controls that change what this page shows. */
.source-link {
  padding: 1px 2px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-size: 12px;
  text-decoration: underline;
  text-decoration-color: var(--energy);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  cursor: pointer;
  transition: background-color .15s ease;
}
.compare-toggle { display: inline-flex; align-items: center; gap: 8px; }
.compare-toggle[aria-pressed="true"] { border-color: transparent; background: var(--accent); color: var(--on-accent); }
/* The menu folds away. On a document this wide it is consulted in bursts and
   read past the rest of the time, and the reader is the point.

   Folded, the column keeps a rail rather than going to nothing. The button that
   brings the menu back has to live somewhere, and a control that moves when you
   use it is a control you hunt for the second time — so it stays at the head of
   its own column in both states, and the rail is what that costs. */
.sidebar-toggle {
  flex: none;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 5px;
  background: transparent;
  color: var(--faint);
  cursor: pointer;
}

.sidebar-toggle:hover { background: var(--energy); color: var(--ink); }

.chevron { width: 12px; height: 12px; }

/* Folded, the chevron turns around: the button points where the menu will go,
   not where it is. */
body.sidebar-collapsed .chevron { transform: scaleX(-1); }

/* Everything the rail does not keep. The head of the column stays, holding the
   button; its eyebrow goes, having no room to be read. */
body.sidebar-collapsed .eyebrow,
body.sidebar-collapsed .behaviour-toolbar,
body.sidebar-collapsed .behaviour-list,
body.sidebar-collapsed .sidebar-export,
body.sidebar-collapsed .sidebar-key,
body.sidebar-collapsed .sidebar-run {
  display: none;
}

/* Only above the breakpoint. Below it the shell is a single column with the
   menu stacked on top, where a 40px rail beside the document means nothing —
   the rules above already reduce it to a strip carrying the button. */
@media (min-width: 901px) {
  /* Two tracks, not three with a zero in the middle: the resizer below is
     `display: none`, which takes it out of the grid altogether, and the
     workspace would then land in that zero-width column. */
  body.sidebar-collapsed .app-shell {
    grid-template-columns: var(--sidebar-rail) minmax(0, 1fr);
  }

  /* The 9px resizer column carried the separation; folded, it is gone. */
  body.sidebar-collapsed .behaviour-sidebar {
    border-right: 1px solid var(--line);
  }

  body.sidebar-collapsed .sidebar-intro {
    padding: 0;
    justify-content: center;
  }
}

body.sidebar-collapsed .sidebar-resizer {
  display: none;
}

.split-icon { width: 12px; height: 12px; display: inline-block; border: 1px solid currentColor; }
.split-icon::after { content: ""; display: block; width: 1px; height: 100%; margin: 0 auto; background: currentColor; }
.compare-toggle:hover { background: var(--energy); color: var(--ink); border-color: transparent; }
/* The framework's link hover: the highlight fills behind the text, which stays ink. */
.source-link:hover { background: var(--energy); color: var(--ink); }

/* Hidden until app.js has drawn the panels and put it in a publisher row. The
   display above would otherwise beat the [hidden] attribute. */
.compare-toggle[hidden] { display: none; }
/* The walk through a document's passages, in that document's own header. It
   used to be one pair of arrows above both panels, stepping a single list that
   ran from one specification into the other. */
.passage-nav { display: flex; align-items: center; gap: 4px; white-space: nowrap; }
.passage-count {
  margin-right: 6px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.passage-nav button {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--muted);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.passage-nav button:hover:not(:disabled) { border-color: transparent; background: var(--energy); color: var(--ink); }
.passage-nav button:disabled { opacity: .35; cursor: default; }

/* Version on the left of its line, the walk on the right. One row, so the
   header gains a control without gaining a line. */
.meta-top {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}


.reader-status {
  display: none;
  padding: 12px 20px;
  border-bottom: 1px solid var(--fail);
  background: var(--gap-soft);
  color: var(--ink);
  font-size: 13px;
}
.reader-status.visible { display: block; }

.document-grid {
  --compare-first: 50%;
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  background: var(--line);
}
.document-grid.compare {
  grid-template-columns:
    minmax(0, var(--compare-first))
    9px
    minmax(0, calc(100% - var(--compare-first) - 9px));
}
.document-resizer { height: 100%; }
.document-panel { min-width: 0; min-height: 0; display: flex; flex-direction: column; background: var(--paper); }
/* A stack of rows, not a row of columns: publishers, then the document at a
   version with what it takes to read it, then the caveat when there is one.
   This header used to hold two things side by side, which is why it was a row;
   its children are now the rows themselves. */
.document-header {
  /* The side padding, named once: the publisher row runs out to the panel's
     edges by exactly this much, so its rule meets the sidebar's across the panel. */
  --header-inline: 24px;
  padding: 0 var(--header-inline) 12px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  border-bottom: 1px solid var(--line-light);
}

/* Comparing, the same header has half the width to say the same five things in.
   The title steps down so it stops wrapping under its own caret. */
.document-grid.compare .document-header { --header-inline: 16px; padding: 0 var(--header-inline) 10px; gap: 6px; }
.document-grid.compare .document-title { font-size: 17px; }
.document-grid.compare .document-version { font-size: 10px; }


.document-title { margin: 0; font-family: var(--display); font-size: 21px; font-weight: 600; }

/* The title is the control that changes the document. It carries no button
   chrome until it is pointed at: a bordered box around the document's name
   would read as decoration on a heading, and the caret is what says it opens. */
.document-picker {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  padding: 2px 8px 2px 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.document-picker:hover { color: var(--accent); }
.document-picker:hover .document-title { background: var(--energy); color: var(--ink); }
.document-picker:focus-visible { outline: 2px solid var(--energy); outline-offset: 2px; }

.picker-caret {
  align-self: center;
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  opacity: .55;
}

.document-picker:hover .picker-caret { opacity: 1; }

/* Version, expand-all, the tier toggles, and now the two controls that used to
   live in the band above: the mode switch and the link to this document at its
   publisher. Flexed rather than the two-column grid it was — the row has five
   groups now, and they wrap where the panel is narrow. */
.document-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 6px 10px;
  color: var(--muted);
  font-size: 11px;
}

/* Comparing, app.js moves this whole row out to be .document-header's own
   last child, below the name/version/Show original row rather than beside
   it: the panel is narrow enough there that a shared row crowds and wraps
   ragged. As a header child it takes the header's full content width from
   the column flex's align-items: stretch (see .document-header) rather than
   from anything set here. The walk leads at the left, "N/M" and then the
   arrows; the view controls, Expand all and then the band toggles, sit at
   the right (.meta-actions). That keeps the walk at the header's bottom-left
   whatever wrapped above: a long title, Show original on one side only, a
   resizer split leaving the two panels different widths. At full width the
   right-aligned cluster reads better, so the rule is scoped to compare. */
.document-grid.compare .document-meta {
  justify-content: flex-start;
  /* 8px, not 10: the right-hand panel, which also carries the scrollbar, has
     the least room for the walk and the view controls on one line. */
  column-gap: 8px;
}
/* The view controls, grouped by app.js in compare mode. Pushed to the right of
   the row, and where the walk and they do not fit on one line (two panels at
   1024px) they wrap below it as one group, still at the right. */
.meta-actions {
  margin-left: auto;
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 6px 8px;
}
/* At a panel's narrowest -- two panels sharing 1024px, a behaviour with
   passages selected so the arrows read "N of M passages" and the toggles
   carry counts, the widest either gets -- the arrows and the three tier
   toggles together still overrun the row before Expand all even joins it.
   The sentence "N of M passages" gives way first: present for a screen
   reader, off-screen for everyone else, in compare mode only. Its short form
   takes its place on screen, "N/M" before the arrows (.passage-count-short),
   because a reader walking two documents still wants to know where the walk
   is. The toggles then trim their own padding and gap, a size step matching
   the title and version reductions just above, and the view controls wrap
   below the walk where the row still does not fit. */
.document-grid.compare .passage-count {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.document-grid.compare .passage-nav { position: relative; }
/* The short counter is compare mode's alone: one document has room for the
   sentence. Hidden from screen readers in the markup, which hear the sentence. */
.passage-count-short { display: none; }
.document-grid.compare .passage-count-short {
  display: inline;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.document-grid.compare .tier-toggle { padding: 3px 5px; gap: 4px; }
.document-grid.compare .rail-legend { gap: 3px; }
.document-version { font-family: var(--mono); font-size: 11px; }
.document-focus-toggle {
  padding: 2px 4px;
  border: 0;
  border-bottom: 2px solid var(--energy);
  background: transparent;
  color: var(--ink);
  font-size: 11px;
  cursor: pointer;
  transition: background-color .15s ease;
}
.document-focus-toggle:hover { background: var(--energy); }
/* The toggles carry their counts, which makes the legend wide enough to overrun a
   phone-width header. Each button stays unbroken (nowrap); the row wraps instead. */
.rail-legend {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}
/* Neutral: the legend explains intensity, and the colour belongs to the behaviour. */
.legend-mark { width: 3px; height: 9px; display: inline-block; border-radius: 2px; background: var(--muted); }
.legend-mark.adjacent { margin-left: 3px; opacity: .4; }

/* Tier toggles: the legend is the control. Each mark-and-word pair is a button; a
   pressed pair sits enclosed in a small bordered well, an unpressed one fades but
   keeps its footprint. Mark weight orders the tiers: heavy bar = defining, solid =
   core, faint = related -- the same weights the passage rail carries. */
.tier-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  color: var(--faint);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}
.tier-toggle .legend-mark { background: currentColor; }
.tier-toggle .legend-mark.adjacent { margin-left: 0; }
.tier-toggle:hover { color: var(--ink); border-color: var(--line); }
.tier-toggle[aria-pressed="true"] {
  border-color: transparent;
  background: rgb(183 201 75 / .32);
  color: var(--ink);
}
/* The run block sits under the key, closing the sidebar: collapsed it is one line of
   run identity, opened it is the payload's full provenance. */
.sidebar-run {
  padding: 10px 22px 14px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 11px;
}
.sidebar-run > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 6px;
}
.sidebar-run > summary::-webkit-details-marker { display: none; }
.sidebar-run > summary::before { content: "▸"; opacity: .6; font-size: 9px; }
.sidebar-run[open] > summary::before { content: "▾"; }
.sidebar-run > summary:hover { color: var(--ink); }
/* A pin that could not be served still renders the page; the marker is the only
   on-screen sign that what you asked for is not what you are looking at. */
.sidebar-run.fell-through > summary::after {
  content: "pin unavailable";
  margin-left: auto;
  padding: 1px 6px;
  border: 1px solid currentColor;
  border-radius: 3px;
  color: var(--adjacent-mark);
  font-size: 10px;
}
.run-detail { margin: 9px 0 0; display: grid; grid-template-columns: 1fr; gap: 2px; }
.run-detail dt { color: var(--faint); font-size: 11px; }
.run-detail dd { margin: 0 0 7px; color: var(--muted); font-family: var(--mono); font-size: 11px; overflow-wrap: anywhere; }

.tier-count { font-variant-numeric: tabular-nums; opacity: .7; }
/* A tier this data cannot reach: dimmed, not clickable, and it keeps its count (0)
   so the reason is legible rather than implied by silence. */
.tier-toggle.unreachable {
  opacity: .4;
  cursor: not-allowed;
  text-decoration: line-through;
}
.tier-toggle.unreachable:hover { color: var(--faint); border-color: transparent; }
.legend-mark.defining { width: 5px; }
.document-scroll { position: relative; flex: 1; min-height: 0; overflow: auto; scroll-behavior: smooth; }

/* Half the window of text, a quarter of it either side.
 *
 * Proportional rather than the 780px box this used to be: with the menu folded
 * the panel is most of the window, and a fixed measure left the spec as a
 * ribbon down the middle of a wide empty field.
 *
 * Measured against the window, not the panel. A quarter of the *panel* would
 * make the column narrower whenever the menu is open than the fixed box it
 * replaces — 570px against 624px — which is the opposite of the point. Against
 * the window the measure holds at half the screen whether the menu is there or
 * not, and only the gutters move.
 *
 * The `max` is a floor, for the case where the panel is narrower than half the
 * window: the subtraction goes negative, and a negative padding is not dropped
 * politely, it takes the whole declaration with it. Compare mode reaches that
 * case on every screen and sets its own gutters below anyway — a quarter of a
 * half-width panel is a column too narrow to read.
 *
 * Gutters as padding rather than margins, so the passage rules and washes,
 * which are laid on the block and bleed into the space beside the text, still
 * have something to bleed into. */
.document-body {
  width: 100%;
  /* The text, and only the text, on the lighter reading surface: the header rows
     above it stay on the panel's --paper. At least the scroll area's height, so a
     short document leaves no strip of --paper under its last line. */
  min-height: 100%;
  background: var(--reading);
  padding: 56px max(28px, (100% - 50vw) / 2) 120px;
  font-family: var(--reader);
  font-size: 17px;
  line-height: 1.6;
}
.document-grid.compare .document-body { padding-right: 58px; padding-left: 58px; font-size: 16px; }
.document-body h1, .document-body h2, .document-body h3,
.document-body h4, .document-body h5 {
  color: var(--ink);
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.16;
  scroll-margin-top: 60px;
}
.document-body h1 { margin: 0 0 30px; font-size: 40px; }
/* The framework's section heading: a 56px chartreuse rule above the heading,
   not a hairline drawn the width of the column. */
.document-body h2 {
  margin: 62px 0 17px;
  padding-top: 19px;
  font-size: 28px;
  background: linear-gradient(var(--energy), var(--energy)) 0 0 / 56px 3px no-repeat;
}
.document-body h3 { margin: 42px 0 14px; font-size: 22px; }
.document-body h4 { margin: 32px 0 12px; font-size: 18px; }
.document-body h5 { margin: 26px 0 9px; color: var(--muted); font-size: 13px; font-weight: 600; }
.document-body .section-heading { position: relative; }
.section-heading-button {
  width: 100%;
  padding: 0;
  display: flex;
  align-items: baseline;
  gap: 12px;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  line-height: inherit;
  text-align: left;
  cursor: pointer;
}
.section-heading-button .section-title { flex: 1; }
.section-heading-button .section-chevron {
  flex: none;
  color: var(--faint);
  font-family: var(--ui);
  font-size: 11px;
  transition: transform .15s ease;
}
.section-heading.section-collapsed {
  margin: 8px 0 !important;
  padding: 0 !important;
  border: 0 !important;
}
.section-heading.section-collapsed .section-heading-button {
  min-height: 34px;
  padding: 7px 14px;
  border: 1px solid var(--muted);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-family: var(--ui);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.35;
  transition: background-color .15s ease, color .15s ease;
}
.section-heading.section-collapsed .section-heading-button:hover {
  border-color: transparent;
  background: var(--energy);
  color: var(--ink);
}
.section-heading.section-collapsed .section-chevron { transform: rotate(-90deg); }
.section-heading.section-has-passage > .section-heading-button::before {
  content: "";
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--energy);
  transform: translateY(-2px);
}
.document-body p { margin: 0 0 1.05em; }
/* The framework's link: ink text over a 2px chartreuse underline; hover fills
   the highlight behind it and the text stays ink. */
.document-body a {
  color: var(--ink);
  text-decoration: none;
  box-shadow: inset 0 -2px 0 var(--energy);
  transition: background-color .15s ease;
}
.document-body a:hover { background: var(--energy); }
.document-body strong { font-weight: 600; }
.document-body em { color: var(--muted); }
.document-body ul, .document-body ol { margin: 0 0 1.2em; padding-left: 1.45em; }
.document-body li { margin: .35em 0; padding-left: .18em; }
/* Bullets are 6px chartreuse circles. Ordered lists keep their numerals, in
   mono, because a numeral is data. */
.document-body ul { list-style: none; padding-left: 1.15em; }
.document-body ul > li { position: relative; }
.document-body ul > li::before {
  content: "";
  position: absolute;
  top: .62em;
  left: -.95em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--energy);
}
.document-body ol > li::marker { font-family: var(--mono); font-size: .85em; color: var(--muted); }
.document-body blockquote {
  margin: 1.4em 0;
  padding: .2em 0 .2em 1.2em;
  border-left: 3px solid var(--energy);
  color: var(--muted);
}
.document-body hr { height: 1px; margin: 45px 0; border: 0; background: var(--line); }
.document-body .code-block {
  margin: 1.1em 0 1.8em;
  padding: 15px 17px;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--chrome-deep);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.55;
  white-space: pre-wrap;
}
.document-body .admonition {
  margin: 1.35em 0;
  padding: 13px 16px 2px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--energy);
  background: var(--chrome-deep);
}
.document-body .admonition-label {
  margin-bottom: 7px;
  color: var(--muted);
  font-family: var(--display);
  font-size: 12px;
  font-weight: 600;
}
.document-body .raw-table { overflow: auto; font-family: var(--mono); font-size: 11px; white-space: pre; }
.zero-coverage {
  margin: 0 0 36px;
  padding: 16px 18px;
  border: 1px solid var(--fail);
  border-left: 3px solid var(--fail);
  border-radius: 4px;
  background: var(--gap-soft);
  font-family: var(--ui);
  font-size: 13px;
  line-height: 1.45;
}
.zero-coverage strong { display: block; margin-bottom: 3px; color: var(--fail); }
.zero-coverage span { color: var(--muted); }

/* Every colour on a passage is written by app.js into --tint (the wash), --gutter (one
   margin rule per behaviour, solid or broken by group) and --bh-primary, all of them in
   terms of the palette's --hue-N, so switching surfaces repaints the highlights without
   re-annotating them. The gutter's -size and -pos place each behaviour's rule in its own
   column; the wash is a single layer and needs neither.

   The rules hang off the right margin, not the left: on the left they sat in the same
   column as an ordered list's numbers and a blockquote's rule, and a highlighted list item
   had its marker struck through. Nothing but the passage rail lives on the right. */
.passage {
  position: relative;
  margin-right: -12px !important;
  margin-left: -12px !important;
  padding: 5px 12px;
  border-radius: 3px;
  background-image: var(--tint);
  box-decoration-break: clone;
}
.passage::before {
  content: "";
  position: absolute;
  top: 5px;
  bottom: 5px;
  right: calc(-7px - var(--gutter-width, 2px));
  width: var(--gutter-width, 2px);
  border-radius: 2px;
  background-image: var(--gutter);
  background-size: var(--gutter-size, auto);
  background-position: var(--gutter-pos, 0 0);
  background-repeat: no-repeat;
}
.passage.current {
  background-image: var(--tint-strong);
  box-shadow: 0 0 0 1px rgb(var(--bh-primary) / .5);
}
.passage.current::before { top: 2px; bottom: 2px; }
/* The strip above a passage carries the behaviour names only. Why the passage was selected
   sits behind the question mark at the right of the strip: the role sentences are long
   enough that set out in the open they read as a second document over the first. */
.passage-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 2px 0 5px;
}
.passage-label {
  color: rgb(var(--bh));
  font-family: var(--ui);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.35;
}
.passage-label + .passage-label::before {
  content: ",";
  margin-right: 8px;
  color: var(--faint);
}

.passage-why {
  flex: none;
  position: relative;
  width: 15px;
  height: 15px;
  margin-left: auto;
  padding: 0;
  border: 1px solid rgb(var(--bh-primary) / .45);
  border-radius: 50%;
  background: transparent;
  color: rgb(var(--bh-primary));
  font-family: var(--ui);
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  opacity: .62;
  transition: opacity .15s ease, background-color .15s ease;
}
.passage-why:hover,
.passage-why:focus-visible,
.passage-why[aria-expanded="true"] {
  opacity: 1;
  background: rgb(var(--bh-primary) / .14);
}
/* The hover legend. Anchored to the right edge so it opens inwards over the text rather
   than off the panel, and never intercepts the pointer on its way to the button. */
.passage-why::after {
  content: attr(data-tip);
  position: absolute;
  z-index: 4;
  top: calc(100% + 5px);
  right: 0;
  padding: 3px 7px;
  border: 1px solid var(--muted);
  border-radius: 4px;
  background: var(--paper);
  color: var(--muted);
  font-family: var(--ui);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.3;
  text-transform: none;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s ease;
}
.passage-why:hover::after,
.passage-why:focus-visible::after { opacity: 1; }
.passage-why[aria-expanded="true"]::after { content: none; }

/* Copy locator and Copy link, just before the question mark. Out of sight until
   they are wanted: a light olive when the pointer is over the block or focus is
   inside it, full on their own hover or focus. Colour and opacity only, over
   150ms; nothing moves. Where there is no hover, the current passage and a tapped
   one show them. */
:is(.passage-copy, .passage-feedback) {
  flex: none;
  width: 18px;
  height: 18px;
  padding: 2px;
  border: 0;
  border-radius: 3px;
  background: transparent;
  color: var(--muted);
  line-height: 0;
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s ease, color .15s ease, background-color .15s ease;
}
:is(.passage-copy, .passage-feedback) svg { display: block; width: 14px; height: 14px; }
.passage-copy[data-copy="locator"] { margin-left: auto; }
.passage-head :is(.passage-copy, .passage-feedback) ~ .passage-why { margin-left: 0; }
.passage:hover :is(.passage-copy, .passage-feedback),
.passage:focus-within :is(.passage-copy, .passage-feedback) { opacity: .55; }
/* As specific as the two rules above, and after them, so an icon's own hover or
   focus wins over the block's. */
.passage :is(.passage-copy, .passage-feedback):hover,
.passage :is(.passage-copy, .passage-feedback):focus-visible { opacity: 1; color: var(--ink); }
@media (hover: none) {
  .passage.current :is(.passage-copy, .passage-feedback),
  .passage.touched :is(.passage-copy, .passage-feedback) { opacity: .55; }
}
/* The tick a successful copy shows for two seconds (markCopied, in app.js). Full
   opacity and --accent, whether or not the pointer is still over the button: a
   plain .passage-copy.copied would be as specific as .passage-copy itself and lose
   to .passage .passage-copy:hover above it, dimming the tick back to .55 under a
   pointer that has not moved since the click. Matching the same .passage ancestor
   here keeps this rule at least as specific, and it is written after what it must
   beat. */
.passage .passage-copy.copied,
.passage .passage-copy.copied:hover,
.passage .passage-copy.copied:focus-visible { opacity: 1; color: var(--accent); }
/* What a refused clipboard selects instead of copying the link. */
.passage-link {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  overflow-wrap: anywhere;
}
.passage-link[hidden] { display: none; }

/* A paragraph's own copy icons, when no passage cites it (setupBlockCopy): one pair,
   stacked in the gutter at the paragraph's right, clear of its text and inside the
   rail, which sits at the scroll box's far edge. Out of sight until the pointer is
   over the paragraph or focus is in it, as a passage's are. */
.holds-copy { position: relative; }
.block-copy {
  position: absolute;
  top: 0;
  right: -30px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.block-copy :is(.passage-copy, .passage-feedback) { margin: 0; }
.holds-copy:hover > .block-copy :is(.passage-copy, .passage-feedback),
.holds-copy:focus-within > .block-copy :is(.passage-copy, .passage-feedback) { opacity: .55; }
.holds-copy .block-copy :is(.passage-copy, .passage-feedback):hover,
.holds-copy .block-copy :is(.passage-copy, .passage-feedback):focus-visible { opacity: 1; color: var(--ink); }
@media (hover: none) {
  .holds-copy.touched > .block-copy :is(.passage-copy, .passage-feedback),
  .linked-block > .block-copy :is(.passage-copy, .passage-feedback) { opacity: .55; }
}
/* The same tick as the passage-head rule above, reached through the toolbar's own
   ancestor chain. This is the specificity trap the gutter sets: .holds-copy .block-copy
   .passage-copy:hover is more specific than the passage-head rule, so a .copied selector
   built for that rule alone would win in a passage's head and still lose here, at .55
   opacity, while the pointer sits over the gutter icon it was just pressed with. */
.holds-copy .block-copy .passage-copy.copied,
.holds-copy .block-copy .passage-copy.copied:hover,
.holds-copy .block-copy .passage-copy.copied:focus-visible { opacity: 1; color: var(--accent); }
/* What a refused clipboard selects under a paragraph with no note to open. */
.block-copy-fallback {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  overflow-wrap: anywhere;
}
/* The paragraph a link opened on, for a moment: a chartreuse outline, the
   framework's active mark, not a behaviour's colour. */
.linked-block {
  outline: 2px solid var(--energy);
  outline-offset: 4px;
  border-radius: 2px;
}

.passage-rationale {
  display: block;
  margin: 0 0 7px;
  padding: 6px 9px;
  border-right: 2px solid rgb(var(--bh-primary) / .5);
  border-radius: 3px 0 0 3px;
  background: rgb(var(--bh-primary) / .07);
  font-family: var(--ui);
  font-size: 13px;
  line-height: 1.45;
}
.passage-rationale[hidden] { display: none; }
.passage-reason { display: block; color: var(--muted); }
.passage-reason + .passage-reason { margin-top: 5px; }
.passage-reason-behaviour {
  color: rgb(var(--bh));
  font-size: 11px;
  font-weight: 600;
}
.passage-reason-behaviour::after { content: ": "; }

.passage-rail {
  position: sticky;
  z-index: 3;
  top: 0;
  float: right;
  width: 14px;
  height: 100%;
  margin-left: -14px;
  pointer-events: none;
}
.passage-rail::before {
  content: "";
  position: absolute;
  top: 8px;
  right: 5px;
  bottom: 8px;
  width: 1px;
  background: var(--line);
}
.rail-mark {
  position: absolute;
  right: 3px;
  width: 4px;
  min-height: 4px;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background-color: transparent;
  background-image: var(--rail);
  opacity: .85;
  pointer-events: auto;
  cursor: pointer;
}
.rail-mark:hover { width: 7px; opacity: 1; }
/* A mark banded down its height is a passage more than one behaviour cites. */
.rail-mark.overlap { width: 6px; }
.rail-mark.current {
  right: 1px;
  width: 9px;
  min-height: 7px;
  /* The gap ring is the ground the rail sits on, so it takes the reading surface. */
  box-shadow: 0 0 0 1px var(--reading), 0 0 0 2px var(--energy);
  opacity: 1;
}

/* One focus ring for the whole surface: 2px chartreuse, always visible. */
button:focus-visible, a:focus-visible, .column-resizer:focus-visible,
summary:focus-visible, dialog:focus-visible {
  outline: 2px solid var(--energy);
  outline-offset: 2px;
}

@media (max-width: 900px) {
  body { overflow: auto; }
  .site-header nav a:not(.active) { display: none; }
  .app-shell { height: auto; min-height: calc(100vh - 54px); grid-template-columns: 1fr; }
  .behaviour-sidebar { border-bottom: 1px solid var(--line); }
  .column-resizer { display: none; }
  .sidebar-intro { padding: 14px 20px; }
  .behaviour-list { display: flex; overflow-x: auto; padding: 8px; }
  .behaviour-group { min-width: 220px; border-bottom: 0; border-right: 1px solid var(--line); }
  .sidebar-export {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 10px 20px;
  }
  .download-passages { width: auto; }
  .download-hint { text-align: left; }
  .sidebar-key { display: none; }
  .workspace { min-height: 75vh; }
  .document-grid, .document-grid.compare { min-height: 70vh; grid-template-columns: 1fr; }
  .document-panel { min-height: 70vh; }
  .document-grid.compare .document-panel { min-height: 65vh; }
  body.embedded { overflow: hidden; }
  body.embedded .app-shell { min-height: 0; }
  body.embedded .workspace { min-height: 0; }
  body.embedded .document-grid,
  body.embedded .document-grid.compare,
  body.embedded .document-panel,
  body.embedded .document-grid.compare .document-panel { min-height: 0; }
}

@media (max-width: 620px) {
  .site-header { padding: 0 16px; }
  .site-footer { padding: 0 16px; }
  /* Two names and a menu do not fit. The mark carries the collective on its
     own here, and its name is still a link in the footer. */
  .collective,
  .brand-divider { display: none; }
  /* The credit line alone. The bar's height is a constant the shell subtracts,
     so nothing here may wrap: at this width the two halves together take three
     lines and the second is cut off mid-sentence. The pointer it carries is in
     the README and on the methodology page, both of which have room. */
  .site-footer span + span { display: none; }
  .document-header,
  .document-grid.compare .document-header { --header-inline: 15px; padding: 0 var(--header-inline) 11px; }
  /* Asymmetric on a phone: the right margin has to hold the passage rules and the rail,
     the left holds nothing. */
  .document-body, .document-grid.compare .document-body { padding: 38px 46px 90px 28px; font-size: 16px; }
  .document-body h1 { font-size: 34px; }
  .document-body h2 { font-size: 25px; }
}

@media (prefers-reduced-motion: reduce) {
  .document-scroll { scroll-behavior: auto; }
  .section-heading-button .section-chevron { transition: none; }
  :is(.passage-copy, .passage-feedback, .document-feedback) { transition: none; }
}

/* ---------- reader test: no behaviour under test ---------- */

.behaviour-empty {
  margin: 4px 14px;
  padding: 16px 15px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--chrome-deep);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.55;
}
.behaviour-empty strong { display: block; margin-bottom: 5px; color: var(--ink); }
.behaviour-empty p { margin: 0; }

/* The Mapped / Mapping pending key describes nothing while the payload is empty, and there is
   nothing to take away either. */
body.no-behaviours .sidebar-key,
body.no-behaviours .sidebar-export { display: none; }

/* .rail-legend sets its own display, which would otherwise beat the [hidden] default
   when the reader hides the highlight legend for want of a behaviour. */
.document-meta [hidden] { display: none; }

/* panel rationale: model-vote list uses newlines */
.passage-reason-role { white-space: pre-line; }
/* The passage's locator under the reason it was cited: data, so mono, and free to
   break anywhere, since a locator is one long string with few natural breaks. */
.passage-locator {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  overflow-wrap: anywhere;
}

/* The list a document's title opens: one entry per registered document, so it
   grows with every spec a reader adds. Comparing, each panel opens its own and
   changes only its own half of the pair. */
.spec-picker {
  position: fixed;
  inset: auto;
  width: min(320px, calc(100vw - 24px));
  max-height: min(60vh, 420px);
  overflow: auto;
  padding: 6px;
  border: 1px solid var(--muted);
  border-radius: 4px;
  background: var(--paper);
}

.spec-picker::backdrop { background: transparent; }

.spec-choice {
  width: 100%;
  display: block;
  padding: 8px 10px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.spec-choice:hover { background: var(--chrome-deep); color: var(--ink); }
.spec-choice[aria-selected="true"] { color: var(--ink); }
.spec-choice-lab { display: block; font-size: 13px; font-weight: 600; }
.spec-choice small { display: block; margin-top: 2px; color: var(--faint); font-family: var(--mono); font-size: 11px; }

/* Local mode: the marker that this page is showing specifications registered on this
   machine, and the nav link to the analysis surface that only exists once a user
   specification is registered. Added by site/shared/local-mode.js. */
.local-data-note {
  /* Third child of a space-between header built for two: without an auto margin the
     free space is split into two equal gaps and the marker floats to the middle of
     them -- a position that varies with nav length and jumps ~200px when the 900px
     query collapses the nav. margin-right:auto absorbs that space before
     justify-content sees it, so the marker stays beside the wordmark at every width. */
  margin: 0 auto 0 16px;
  padding: 2px 8px;
  border: 1px solid var(--muted);
  border-radius: 999px;
  color: var(--accent);
  font-size: 11px;
  white-space: nowrap;
  cursor: help;
}

/* The 16px above is 16px the wordmark no longer has, which moves its wrap threshold
   up: measured, the margin alone pushes the width at which the wordmark breaks out of
   the fixed-height header from 380 to 395 on the panel, newly breaking 390/393. Below
   400 there is not room for wordmark + marker + nav on one row at all, so the marker
   stands down. Scoped to the body flag local-mode.js sets, so a bundled-only site --
   which never sets it -- is untouched: measured drift 0 at every width. */
@media (max-width: 400px) {
  body[data-local-data] .local-data-note { display: none; }
}

/* A document the index read in translation says so in a band under its header,
   across the panel and above the text it is about.

   Rust marks it. That is a deliberate departure, taken by the operator and
   recorded here: the framework reserves --fail for status, and a machine
   translation is a caveat rather than a failure, but rust is the palette's only
   warm colour and the operator asked for this notice to read as a warning
   rather than blend into the header.

   The rust is the band's left rule, not its words. As 11px text on
   --chrome-deep it measured 4.07:1 on daylight and 3.53:1 on umber, under the
   4.5:1 AA asks of text. As a rule it is a non-text mark, which needs 3:1, and
   clears it in both. The words are --ink: 10.95:1 on daylight, 10.07:1 on
   umber. Left-aligned like every other line of the reader, with the rule taking
   2px of the left padding so the words keep their place. */
.document-translation {
  margin: 0;
  padding: 6px 12px 6px 22px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-left: 2px solid var(--fail);
  border-bottom: 1px solid var(--line-light);
  background: var(--chrome-deep);
  color: var(--ink);
  font-size: 11px;
  line-height: 1.4;
  text-align: left;
}
/* The display above would otherwise beat the hidden attribute. */
.document-translation[hidden] { display: none; }
.translation-text { flex: 1; min-width: 0; }
/* The notice's close control: a plain ×, in the band's own ink, centred at its
   right end. The negative margins keep the band no taller for it. */
.translation-dismiss {
  flex: none;
  width: 20px;
  height: 20px;
  margin: -3px 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  font-family: var(--ui);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.translation-dismiss:hover { background: var(--energy); color: var(--ink); }
/* What remains once the notice is dismissed, beside Show original. */
.translation-flag { color: var(--muted); font-size: 12px; white-space: nowrap; }
.translation-flag[hidden] { display: none; }

/* The mark that opens a passage's original. A glyph, not an icon: the framework
   carries no icon library and no emoji, and the character reads as "writing" to
   anyone who can read the original it opens. */
.original-open {
  /* The glyph is drawn, not written: the reader anchors citations by the text
     content of a block (findPassageBlocks), so a character added to the block
     would change the text a stored quote is matched against. The button's
     accessible name is its aria-label. */
  margin-left: 5px;
  padding: 0 3px;
  border: 0;
  border-bottom: 2px solid var(--energy);
  background: transparent;
  color: var(--muted);
  font-family: var(--ui);
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}

.original-open::after { content: "文"; }
.original-open:hover { background: var(--energy); color: var(--ink); }

/* The original itself, in the top layer like the key's notes, placed under the
   glyph that opened it. */
.original-note {
  position: fixed;
  inset: auto;
  width: min(420px, calc(100vw - 32px));
  max-height: min(60vh, 460px);
  overflow: auto;
  padding: 14px 16px;
  border: 1px solid var(--muted);
  border-radius: 4px;
  background: var(--paper);
  color: var(--ink);
}

.original-note::backdrop { background: transparent; }

.original-note-label {
  margin: 0 0 8px;
  color: var(--muted);
  font-family: var(--ui);
  font-size: 11px;
}

.original-note-body {
  margin: 0;
  font-size: 15px;
  line-height: 1.75;
  white-space: pre-wrap;
}

/* The header's rows: publishers, then the document being read at a version,
   then the caveat if there is one. Each panel carries its own set, so comparing
   asks the same two questions twice, once per side, in the same places. */
/* The first row of every panel, and the top line of the reader now that the strip
   of behaviour tags above the documents is gone: publishers at the left, and at
   the right of the last panel's row the switch into and out of compare. It is
   exactly --panel-header-height tall and runs out to the panel's edges, so its
   rule falls on the sidebar header's line, menu open or folded, one panel or two.
   The publishers sit on the rule, so the chosen one's underline meets it.

   Exactly, not at least: a row that grew would move its rule off the line. So
   where a panel is narrow (two panels, a widened menu, more publishers than fit)
   the publishers stay on one line and scroll sideways rather than wrap, and
   Compare gives up its word before that, keeping its icon, its tooltip and its
   accessible name. The row is a size container for that one question. */
.provider-row {
  container-type: inline-size;
  height: var(--panel-header-height);
  margin: 0 calc(-1 * var(--header-inline)) 8px;
  padding: 0 var(--header-inline);
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  border-bottom: 1px solid var(--line);
}
.provider-row .compare-toggle { flex: none; align-self: center; }
@container (max-width: 440px) {
  .provider-row .compare-toggle { padding: 8px 10px; }
  .provider-row .compare-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
}

.provider-tabs {
  display: flex;
  flex-wrap: nowrap;
  gap: 2px;
  min-width: 0;
  /* Scrolls rather than wraps (see .provider-row), and a scrolling box clips what
     sits outside it. The padding is room for a focused tab's ring, and the
     negative margins give it back, so the tabs sit where they would without it:
     on the row's rule, the chosen one's marker overlapping it by a pixel. */
  overflow-x: auto;
  padding: 2px 2px 3px;
  margin: -2px -2px -3px;
  scrollbar-width: none;
}
.provider-tabs::-webkit-scrollbar { display: none; }

/* Labels large enough to read at a glance, in a row that does not grow: the room
   comes out of the tab's own vertical padding, not the row's height. The others
   are --faint, quieter than the chosen one and still AA on the header's ground
   (4.71:1 daylight, 4.72:1 umber, against the chosen ink's 13.08:1 and 9.94:1). */
.provider-tab {
  padding: 3px 10px 4px;
  border: 0;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  background: transparent;
  color: var(--faint);
  font-family: var(--ui);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.25;
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease;
}

.provider-tab:hover { color: var(--ink); }
/* The chosen publisher, unmistakable: ink at 600 over the framework's chartreuse
   active marker, which marks and never writes. */
.provider-tab[aria-pressed="true"] {
  border-bottom-color: var(--energy);
  color: var(--ink);
  font-weight: 600;
}
/* The ring just outside the tab, inside the strip's padding, where the strip's
   scrolling box cannot clip it. */
.provider-tab:focus-visible { outline-offset: 0; }

.document-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.document-identity { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.document-identity .document-version {
  margin-left: 8px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 400;
}

/* The note icon beside the document's title. Unlike a paragraph's own (see
   .passage-copy, .passage-feedback below) it does not wait for a hover: the
   header is not a fleeting passage, so it stays visible on its own. */
.document-feedback {
  flex: none;
  align-self: center;
  width: 22px;
  height: 22px;
  padding: 3px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--muted);
  line-height: 0;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.document-feedback svg { display: block; width: 15px; height: 15px; }
.document-feedback:hover { background: var(--energy); color: var(--ink); }
.document-feedback:focus-visible { outline: 2px solid var(--energy); outline-offset: 2px; }

/* "Copied", in the button itself, for the two seconds it shows (markCopied, in
   app.js). More discreet than a tick beside a floating pill: one thing instead
   of two. The button's own width (18px, set above) only fits an icon, so it
   grows to fit the word instead, in a small font -- the only way a word fits
   into what is otherwise an 18px control. */
.passage-copy.copied {
  display: inline-flex;
  align-items: center;
  width: auto;
  padding: 2px 5px;
}
.copied-label {
  font-family: var(--ui);
  font-size: 10px;
  line-height: 1.4;
  white-space: nowrap;
}

/* ---------- feedback on a paragraph ---------- */

/* Modal, centred, and no wider than prose wants to be. The framework's one
   permitted box: a 1px rule around a single highlighted element per view. */
.feedback-dialog {
  width: min(520px, calc(100vw - 32px));
  max-height: min(86vh, 720px);
  padding: 0;
  border: 1px solid var(--muted);
  border-radius: 4px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--ui);
}
.feedback-dialog::backdrop { background: rgba(35, 40, 27, .55); }
.feedback-form { display: block; padding: 18px 20px 20px; overflow-y: auto; max-height: inherit; }

.feedback-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}
.feedback-head h2 {
  margin: 0;
  font-family: var(--display);
  font-size: 18px;
  font-weight: 600;
}
.feedback-close {
  border: 0;
  background: none;
  padding: 2px 6px;
  color: var(--faint);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.feedback-close:hover { background: var(--energy); color: var(--ink); }
.feedback-close:focus-visible { outline: 2px solid var(--energy); outline-offset: 2px; }

/* The paragraph this is about, in the family the index writes data in. */
.feedback-locator {
  margin: 6px 0 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line-light);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.feedback-field { margin: 0 0 16px; }
.feedback-field[hidden] { display: none; }
.feedback-field label,
.feedback-vote legend,
.feedback-visibility legend {
  display: block;
  margin-bottom: 6px;
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
}
.feedback-field input,
.feedback-field textarea {
  display: block;
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--reading);
  color: var(--ink);
  font-family: var(--ui);
  font-size: 14px;
  line-height: 1.5;
}
.feedback-field textarea { resize: vertical; min-height: 72px; }
.feedback-field input:focus-visible,
.feedback-field textarea:focus-visible {
  outline: 2px solid var(--energy);
  outline-offset: 1px;
}
/* Shown, not editable: the behaviours are read off the paragraph. Readonly
   rather than disabled, so it keeps its place in the tab order and a screen
   reader still reads the context every other reader can see. */
.feedback-field input[readonly] {
  background: transparent;
  border-style: dashed;
  color: var(--muted);
}
/* The name field while the private toggle is on: a private note is shown to
   nobody, so a name on it would mean nothing. Disabled, not hidden, so the
   toggle's effect on it is seen rather than the field vanishing. */
.feedback-field input:disabled {
  opacity: .55;
  cursor: default;
}
.feedback-note {
  display: block;
  margin-top: 5px;
  color: var(--faint);
  font-size: 12px;
  line-height: 1.45;
}

.feedback-vote, .feedback-visibility {
  margin: 0 0 16px;
  padding: 0;
  border: 0;
}
.feedback-thumbs { display: flex; gap: 8px; }
/* A pill, as every button on a Polaris surface is. Pressed, it takes the energy
   colour at the weight a selected table row takes it. */
.thumb {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-family: var(--ui);
  font-size: 13px;
  cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.thumb svg { width: 14px; height: 14px; display: block; }
.thumb:hover { border-color: var(--muted); }
.thumb:focus-visible { outline: 2px solid var(--energy); outline-offset: 2px; }
/* Pressed, it takes the energy colour at full strength with ink text, which is
   what every other active control in this reader does (.depth-head, the tier
   toggles). color-mix appears nowhere in this file and does not start here. */
.thumb[aria-pressed="true"] {
  background: var(--energy);
  border-color: var(--muted);
  color: var(--ink);
}

.feedback-choice {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2px 8px;
  margin-bottom: 10px;
  font-weight: 400;
  cursor: pointer;
}
.feedback-choice input { grid-row: 1 / span 2; margin-top: 3px; accent-color: var(--accent); }
.feedback-choice input:focus-visible { outline: 2px solid var(--energy); outline-offset: 2px; }
.feedback-choice .choice-title { font-size: 14px; }
.feedback-choice .choice-note { color: var(--faint); font-size: 12px; line-height: 1.45; }

/* Never seen, never reached by the keyboard, and not announced. */
.feedback-trap {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.feedback-outcome {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-line;
}
.feedback-outcome:empty { display: none; }
.feedback-outcome.problem { color: var(--fail); }
.feedback-outcome.done { color: var(--muted); }

.feedback-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  border-top: 1px solid var(--line-light);
  margin-top: 4px;
  padding-top: 16px;
}
.feedback-cancel, .feedback-send {
  padding: 7px 18px;
  border-radius: 999px;
  font-family: var(--ui);
  font-size: 14px;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.feedback-cancel { border: 1px solid var(--muted); background: transparent; color: var(--ink); }
.feedback-cancel:hover { border-color: var(--ink); }
.feedback-send { border: 1px solid var(--accent); background: var(--accent); color: var(--paper); }
.feedback-send:hover { background: var(--energy); border-color: var(--energy); color: var(--ink); }
.feedback-send[disabled] { opacity: .55; cursor: default; }
.feedback-cancel:focus-visible, .feedback-send:focus-visible {
  outline: 2px solid var(--energy);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .feedback-close, .thumb, .feedback-cancel, .feedback-send { transition: none; }
}


/* A document note names its document in words, not in the engine's id, so that
   line is prose and drops the mono the framework reserves for data. */
.feedback-locator.prose {
  font-family: var(--ui);
  font-size: 13px;
  color: var(--ink);
}
