/* Aquifer web application stylesheet.
 *
 * The structure is the supplied document-control reference (see DESIGN.md):
 * paper and sheet surfaces, hairline rules, monospace metadata, ownership and
 * revision stated plainly. The scale is reduced for a working application.
 *
 * Rules this file holds to, because the deterministic gate checks them:
 *   - Every colour literal lives in a :root block. Nothing else may name a hex.
 *   - No elevation is expressed with an ad hoc shadow; one token, one dialog.
 *   - Every interactive element has hover, :focus-visible and :disabled states.
 *   - Every transition has a prefers-reduced-motion fallback.
 *   - Attention colour is a marker. It never becomes a surface behind copy.
 */

/* ---------------------------------------------------------------------------
 * Tokens
 * ------------------------------------------------------------------------ */

:root {
  color-scheme: light;

  /* Surfaces */
  --paper: #e6e6e6;
  --sheet: #ffffff;
  --sheet-alt: #f7f7f7;
  --fill: rgba(0, 0, 0, 0.05);
  --fill-strong: rgba(0, 0, 0, 0.09);
  --code-bg: rgba(11, 110, 134, 0.08);

  /* Ink */
  --ink: #333333;
  --muted: #4a4a4a;

  /* Disabled controls. Their own pair rather than `--muted` on `--sheet-alt`,
   * because this is the one place two tokens have to satisfy a constraint
   * TOGETHER: the label and the fill behind it are held to AA as a pair, and
   * binding the label to a body-text token lets a text re-tune move a control
   * label under the threshold without anyone touching a control rule.
   * Measured composited against the panel surface: 8.27:1 light, 13.31:1 dark. */
  --disabled-ink: #4a4a4a;
  --disabled-surface: #f7f7f7;

  /* Rules */
  --rule: rgba(0, 0, 0, 0.3);
  --rule-soft: rgba(0, 0, 0, 0.13);

  /* Meaning */
  --primary: #0b6e86;
  --on-primary: #ffffff;
  --accent: #09566b;
  --attention: #faa41a;
  --attention-ink: #7a4f00;
  --danger: #8c1d18;

  /* Diff row tints.
   *
   * Decorative by construction: a diff row states its operation in the sign
   * character, both line numbers and a word for screen readers before any of
   * this applies. The tints are deliberately weak so they cannot cost the text
   * its contrast — the pairs are measured with the APCA audit rather than
   * eyeballed, and the measurements are in docs/evidence/.
   */
  --diff-added-bg: rgba(9, 86, 107, 0.1);
  --diff-removed-bg: rgba(140, 29, 24, 0.1);
  --ring: #0b6e86;

  /* The one shadow in the application. */
  --shadow-dialog: 0 10px 28px rgba(0, 0, 0, 0.26);

  /* Spacing, 4px base */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;

  /* Shape. One scale. */
  --radius-control: 2px;
  --radius-panel: 2px;

  /* Type */
  --font-display: 'Avenir Next Condensed', 'Helvetica Neue', ui-sans-serif, system-ui, sans-serif;
  --font-body: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', 'Helvetica Neue', arial,
    sans-serif;
  --font-mono: ui-monospace, 'SF Mono', menlo, consolas, 'Liberation Mono', monospace;

  --measure: 72ch;
  --content: 1120px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    color-scheme: dark;

    --paper: #000000;
    --sheet: #012060;
    --sheet-alt: #0a1e3c;
    --fill: rgba(255, 255, 255, 0.07);
    --fill-strong: rgba(255, 255, 255, 0.12);
    --code-bg: rgba(138, 220, 255, 0.12);

    --ink: #ffffff;
    --muted: #e6e6e6;

    --disabled-ink: #e6e6e6;
    --disabled-surface: #0a1e3c;

    --rule: rgba(255, 255, 255, 0.35);
    --rule-soft: rgba(255, 255, 255, 0.16);

    --primary: #0d7391;
    --on-primary: #ffffff;
    --accent: #8adcff;
    --attention: #faa41a;
    --attention-ink: #ffd79a;
    --danger: #ffc9c2;
    --ring: #8adcff;

    /* On the navy sheet these are washes toward the accent and the danger hue.
     * Kept weak so the white body text keeps its contrast on top of them. */
    --diff-added-bg: rgba(138, 220, 255, 0.16);
    --diff-removed-bg: rgba(255, 201, 194, 0.16);

    --shadow-dialog: 0 10px 28px rgba(0, 0, 0, 0.66);
  }
}

:root[data-theme='dark'] {
  color-scheme: dark;

  --paper: #000000;
  --sheet: #012060;
  --sheet-alt: #0a1e3c;
  --fill: rgba(255, 255, 255, 0.07);
  --fill-strong: rgba(255, 255, 255, 0.12);
  --code-bg: rgba(138, 220, 255, 0.12);

  --ink: #ffffff;
  --muted: #e6e6e6;

  --disabled-ink: #e6e6e6;
  --disabled-surface: #0a1e3c;

  --rule: rgba(255, 255, 255, 0.35);
  --rule-soft: rgba(255, 255, 255, 0.16);

  --primary: #0d7391;
  --on-primary: #ffffff;
  --accent: #8adcff;
  --attention: #faa41a;
  --attention-ink: #ffd79a;
  --danger: #ffc9c2;
  --ring: #8adcff;

  --diff-added-bg: rgba(138, 220, 255, 0.16);
  --diff-removed-bg: rgba(255, 201, 194, 0.16);

  --shadow-dialog: 0 10px 28px rgba(0, 0, 0, 0.66);
}

/* ---------------------------------------------------------------------------
 * Base
 * ------------------------------------------------------------------------ */

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0;
  font-weight: 700;
}

h1 {
  font-size: 22px;
  letter-spacing: 0.01em;
  line-height: 1.25;
}

h2 {
  font-size: 15px;
  line-height: 1.3;
  font-weight: 600;
}

h3 {
  font-size: 13px;
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: 0.06em;
}

p {
  margin: 0 0 var(--s3);
  max-width: var(--measure);
}

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

a:hover {
  text-decoration-thickness: 2px;
}

code,
pre,
.mono {
  font-family: var(--font-mono);
  font-size: 12.5px;
}

code {
  background: var(--code-bg);
  padding: 1px 4px;
}

/* Focus is never removed, anywhere. */
:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
 * Document header: the identity's signature, one line of metadata
 * ------------------------------------------------------------------------ */

.doc-head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  align-items: baseline;
  border-bottom: 2px solid var(--ink);
  padding-bottom: var(--s2);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.doc-head .ref {
  color: var(--accent);
}

.section-head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  align-items: baseline;
  justify-content: space-between;
  border-top: 1px solid var(--rule-soft);
  padding-top: var(--s3);
  margin-top: var(--s5);
}

.section-head h2 {
  color: var(--accent);
}

.lede {
  color: var(--muted);
  max-width: var(--measure);
  margin-bottom: var(--s4);
}

/* ---------------------------------------------------------------------------
 * Shell
 * ------------------------------------------------------------------------ */

.shell {
  display: grid;
  grid-template-rows: 48px 1fr;
  height: 100vh;
}

.topbar {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: 0 var(--s4);
  border-bottom: 1px solid var(--rule);
  background: var(--sheet);
}

.wordmark {
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
}

.topbar-spacer {
  flex: 1;
}

.org-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The organization selector. A control, not a label: DESIGN.md:174-175 asks
   for a switcher, and rendering the organization's name in a <span> is the
   thing that shipped instead. Sized to the name so a long one does not push
   the account controls off the bar. */
.org-picker {
  display: inline-flex;
  align-items: center;
}

.org-picker-field {
  width: auto;
  min-width: 160px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: var(--s1) var(--s2);
  border: 1px solid var(--rule);
  background: var(--sheet);
}

.body-row {
  display: grid;
  grid-template-columns: 200px 1fr;
  min-height: 0;
}

.rail {
  border-right: 1px solid var(--rule);
  padding: var(--s4) 0;
  overflow-y: auto;
}

.rail-group {
  padding: 0 var(--s4);
  margin-bottom: var(--s2);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.nav-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2);
  padding: var(--s2) var(--s4);
  border-left: 2px solid transparent;
  color: var(--ink);
  text-decoration: none;
  font-size: 14px;
}

.nav-item:hover {
  background: var(--fill);
}

.nav-item[aria-current='page'] {
  border-left-color: var(--accent);
  font-weight: 600;
}

.nav-count {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
}

.content {
  min-width: 0;
  overflow-y: auto;
  padding: var(--s5) var(--s5) var(--s8);
}

.content-inner {
  max-width: var(--content);
}

/* ---------------------------------------------------------------------------
 * Panels
 * ------------------------------------------------------------------------ */

.panel {
  background: var(--sheet);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: var(--radius-panel);
}

.panel-pad {
  padding: var(--s4);
}

.panel-head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
  align-items: baseline;
  justify-content: space-between;
  border-bottom: 1px solid var(--rule-soft);
  padding: var(--s3) var(--s4);
}

.panel-body {
  padding: var(--s4);
}

.panel + .panel {
  margin-top: var(--s5);
}

/* `minmax(0, …)` ON BOTH TRACKS, and the reason is measured rather than
 * theoretical. A grid track declared `1fr` has an implicit `min-width: auto`,
 * so it refuses to shrink below its content's MIN-CONTENT width — and the
 * review screen's content includes a diff row of `white-space: pre` text,
 * whose min-content width is the whole line. At 200% zoom in a 640 px viewport
 * the stacked track measured 732 px, so `main.content` scrolled sideways by
 * 104 px: the reflow happened, and then the track refused to give ground.
 *
 * `minmax(0, …)` lets the track shrink and the inner scroller do its job.
 * The overflow control for this is in §6 of the evidence document: a detector
 * reading `documentElement` instead of the real scroll container reported 0 px
 * here, and reported 0 px with a 900 px block injected. */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: var(--s5);
  align-items: start;
}

/* ---------------------------------------------------------------------------
 * Toolbar: search and filters sit in one row above the table
 * ------------------------------------------------------------------------ */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
  margin-bottom: var(--s3);
}

.toolbar-grow {
  flex: 1 1 260px;
  min-width: 0;
}

.field-label {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s1);
}

.field {
  width: 100%;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink);
  background: var(--sheet);
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  padding: 6px var(--s2);
  min-height: 32px;
}

/* The same pair as `.btn:disabled`, so "this control is not available" is one
 * convention with one measured figure across every control that has it. */
.field:disabled {
  color: var(--disabled-ink);
  background: var(--disabled-surface);
  cursor: not-allowed;
}

select.field {
  padding-right: var(--s2);
}

.field-fieldset {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

.toolbar .field {
  width: auto;
  min-width: 140px;
}

.toolbar .toolbar-grow .field {
  width: 100%;
}

.checkline {
  display: flex;
  align-items: flex-start;
  gap: var(--s2);
  padding: var(--s2) 0;
}

.checkline + .checkline {
  border-top: 1px solid var(--rule-soft);
}

.checkline input {
  margin: 3px 0 0;
  accent-color: var(--primary);
}

.checkline-text {
  font-size: 14px;
}

.checkline-note {
  display: block;
  color: var(--muted);
  font-size: 13px;
}

/* ---------------------------------------------------------------------------
 * Buttons. One primary per view; the rest are quieter by construction.
 * ------------------------------------------------------------------------ */

.btn {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  border-radius: var(--radius-control);
  border: 1px solid var(--rule);
  padding: 7px var(--s3);
  min-height: 32px;
  cursor: pointer;
  transition: background-color 160ms ease-out, border-color 160ms ease-out,
    color 160ms ease-out;
}

/* A DISABLED CONTROL STILL HAS A LABEL, AND THE LABEL HAS TO READ.
 *
 * This used to be `opacity: 0.55` on the whole element, which is the obvious
 * way to say "not available" and is wrong twice over here. Opacity is applied
 * to the element as a whole, so it drags the TEXT toward the background as
 * well as the fill; and `btn-primary:disabled` set its colour to `--on-primary`
 * (#ffffff) on `--sheet-alt` (#f7f7f7). Composited against the panel surface,
 * measured rather than read off the declarations:
 *
 *   btn-primary :disabled   1.02:1     btn-danger :disabled    3.10:1
 *   btn-secondary :disabled 3.24:1     btn-quiet :disabled     2.77:1
 *
 * in the light scheme; 3.99:1 and 3.98:1 for danger and quiet in the dark one.
 * A reviewer who cannot read the label on the control that approves a release
 * has been told the control exists and been given no way to know what it says.
 *
 * Removing the opacity alone would have been worse than leaving it. White on
 * #f7f7f7 is not "faint", it is an empty rectangle, and the 0.55 was the only
 * thing dragging it off 1.0:1. So the label moves WITH the background: the pair
 * is `--disabled-ink` on `--disabled-surface`, which measures 8.27:1 in the
 * light scheme and 13.31:1 in the dark one. That is the figure to re-check if
 * either token is ever re-tuned; it is a property of the pair, not of the ink.
 *
 * THE STATE IS CARRIED BY SURFACE AND BORDER, NOT BY FAINT TEXT — the residual
 * worth naming. A label that clears AA cannot also be the washed-out grey a
 * disabled control is conventionally drawn in: at 4.5:1 the label is darker
 * than every "muted" grey in the system, and no amount of opacity discipline
 * gets both. So "reads as disabled" is carried by the fill dropping from
 * `--primary` to `--disabled-surface` and the border from `--primary` to
 * `--rule` — tone, weight and border, three channels, none of them the text —
 * plus the natively disabled element and `cursor: not-allowed`. The honest cost
 * is that a disabled primary now resembles a secondary button: both are a pale
 * field behind a hairline rule, and the two are told apart by behaviour rather
 * than by colour. Readability won; that is a deliberate choice, not an
 * oversight, and the alternative is the 1.02:1 above.
 */
.btn:disabled {
  cursor: not-allowed;
  color: var(--disabled-ink);
  background: var(--disabled-surface);
  border-color: var(--rule);
}

.btn-primary {
  color: var(--on-primary);
  background: var(--primary);
  border-color: var(--primary);
}

.btn-primary:hover:not(:disabled) {
  border-color: var(--ink);
}

.btn-secondary {
  color: var(--ink);
  background: var(--sheet);
  border-color: var(--rule);
}

.btn-secondary:hover:not(:disabled) {
  background: var(--sheet-alt);
}

.btn-danger {
  color: var(--danger);
  background: var(--sheet);
  border-color: var(--danger);
}

.btn-danger:hover:not(:disabled) {
  background: var(--sheet-alt);
}

.btn-quiet {
  color: var(--accent);
  background: var(--sheet);
  border-color: transparent;
  padding-left: var(--s2);
  padding-right: var(--s2);
}

.btn-quiet:hover:not(:disabled) {
  background: var(--sheet-alt);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: center;
}

.btn-row-end {
  margin-left: auto;
}

/* ---------------------------------------------------------------------------
 * Tables. The primary listing surface in this application.
 * ------------------------------------------------------------------------ */

.table-scroll {
  display: flex;
  flex-direction: column;
  overflow-x: auto;
}

table.data {
  table-layout: fixed;
  border-collapse: collapse;
}

table.data caption {
  text-align: left;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0 0 var(--s2);
}

table.data th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--sheet-alt);
  border-bottom: 1px solid var(--rule);
  padding: var(--s2) var(--s3);
  white-space: nowrap;
}

table.data td {
  border-bottom: 1px solid var(--rule-soft);
  padding: var(--s2) var(--s3);
  vertical-align: top;
  font-size: 14px;
}

table.data tbody tr:hover {
  background: var(--fill);
}

table.data .col-name {
  width: 44%;
}

table.data .col-owner {
  width: 18%;
}

table.data .col-rev {
  width: 10%;
}

table.data .col-status {
  width: 16%;
}

table.data .col-when {
  width: 12%;
}

.cell-name {
  display: block;
  font-weight: 600;
}

.cell-note {
  display: block;
  color: var(--muted);
  font-size: 13px;
}

/* The two-line clamp belongs to ONE use of this class: the second line of a
   table row, where DESIGN.md:186-187 says the name column carries the
   description and a 44px row has room for two lines of it.

   It does NOT belong to the other use — a `<p class="cell-note">` explaining
   what a screen does or what a button will and will not do. Those are prose,
   and a clamp on prose is not a compactness device: at a narrow width it
   silently deletes the end of the sentence. What it deleted here was the
   editor's own disclosure that saving a draft "changes nothing a reader can
   see until the draft is approved and published" — the sentence a person most
   needs after a save fails, and the one the clamp cut in half.

   So the clamp is scoped to the place it was written for and nowhere else. */
td .cell-note,
th .cell-note {
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.cell-meta {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--muted);
}

.skeleton-row td {
  height: 44px;
}

.skeleton-bar {
  display: block;
  height: 10px;
  background: var(--fill);
}

/* ---------------------------------------------------------------------------
 * Status. Text plus glyph plus colour, never colour alone.
 * ------------------------------------------------------------------------ */

.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--sheet-alt);
  border: 1px solid var(--rule-soft);
  border-radius: var(--radius-control);
  padding: 1px 6px;
  white-space: nowrap;
}

.tag-accent {
  color: var(--accent);
  background: var(--sheet);
}

.tag-attention {
  color: var(--attention-ink);
  background: var(--sheet);
  border-color: var(--attention);
}

.tag-danger {
  color: var(--danger);
  background: var(--sheet);
  border-color: var(--danger);
}

.glyph {
  font-family: var(--font-mono);
  font-weight: 700;
}

.checkpoint {
  display: grid;
  grid-template-columns: 10px 1fr;
  gap: var(--s2);
  align-items: start;
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule-soft);
}

.checkpoint-mark {
  width: 10px;
  height: 10px;
  margin-top: 5px;
  background: var(--attention);
}

.checkpoint-id {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  display: block;
}

.checkpoint-text {
  font-size: 14px;
}

/* ---------------------------------------------------------------------------
 * Callouts. A rule on the left, never a coloured surface behind copy.
 * ------------------------------------------------------------------------ */

.callout {
  border-left: 3px solid var(--rule);
  background: var(--sheet-alt);
  color: var(--ink);
  padding: var(--s3) var(--s4);
  margin: var(--s3) 0;
}

.callout p:last-child {
  margin-bottom: 0;
}

.callout-attention {
  border-left-color: var(--attention);
}

.callout-danger {
  border-left-color: var(--danger);
  color: var(--danger);
  background: var(--sheet);
}

.callout-tag {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s1);
}

.callout-danger .callout-tag {
  color: var(--danger);
}

/* ---------------------------------------------------------------------------
 * Definition lists, record lists, filters
 * ------------------------------------------------------------------------ */

.dl {
  display: grid;
  grid-template-columns: 168px 1fr;
  gap: var(--s2) var(--s4);
  margin: 0;
}

.dl dt {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  padding-top: 2px;
}

.dl dd {
  margin: 0;
  font-size: 14px;
  min-width: 0;
  overflow-wrap: anywhere;
}

.record {
  border-bottom: 1px solid var(--rule-soft);
  padding: var(--s3) 0;
}

.record:first-child {
  border-top: 1px solid var(--rule-soft);
}

.record-head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  align-items: baseline;
  justify-content: space-between;
}

.filter-summary {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s3);
}

/* ---------------------------------------------------------------------------
 * Diff and file listing
 * ------------------------------------------------------------------------ */

.diff {
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.55;
  border: 1px solid var(--rule);
  overflow-x: auto;
  padding: var(--s2) 0;
  margin: 0;
}

/* Four columns: the old line number, the new one, the sign, and the text.
 *
 * The two number columns are not decoration either. After a deletion the same
 * line has different numbers on the two sides, and a reviewer pointing at
 * "line 33" has to be able to say which file they mean.
 */
.diff-line {
  display: grid;
  grid-template-columns: 44px 44px 20px minmax(0, 1fr);
  gap: var(--s2);
  padding: 0 var(--s3);
  white-space: pre;
  border-left: 3px solid transparent;
}

.diff-line .no {
  color: var(--muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.diff-line .sign {
  font-weight: 700;
}

/* NOTHING BELOW IS LOAD-BEARING.
 *
 * Every row already states its operation three ways in the markup: a `+`, `-` or
 * space character, a line number on each side, and the word Added / Removed /
 * Unchanged for a screen reader. The tints and the rules below are the last
 * thing a reader uses, not the first, and removing them costs nothing but the
 * speed of scanning. That ordering is deliberate: a diff is exactly where the
 * temptation to encode meaning in colour lives, and UI-01 forbids it.
 *
 * The left border is a rule, not a colour, so the row still reads as changed in
 * a stylesheet that renders every tint the same.
 */
.diff-added {
  background: var(--diff-added-bg);
  border-left-color: var(--diff-sign-added);
}

.diff-removed {
  background: var(--diff-removed-bg);
  border-left-color: var(--diff-sign-removed);
}

.diff-added .sign {
  color: var(--diff-sign-added);
}

.diff-removed .sign {
  color: var(--diff-sign-removed);
}

/* The word-level marks inside a line.
 *
 * `ins` and `del` are the elements, so a screen reader announces an insertion
 * and a deletion rather than a run of differently-coloured characters. The
 * underline and the strike are separate from the tint for the same reason the
 * sign is: neither mark should depend on colour being distinguishable.
 */
.diff ins {
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 2px;
}

.diff del {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

/* A collapsed run, stated rather than implied. */
.diff-omitted {
  font-family: var(--font-body);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  border-top: 1px solid var(--rule-soft);
  border-bottom: 1px solid var(--rule-soft);
  padding: var(--s2) var(--s3);
  margin: var(--s1) 0;
}

/* The rendered document preview.
 *
 * Unstyled until now, which meant the before/after panes rendered their
 * markdown as an undifferentiated block of text — the preview existed and
 * looked like source.
 */
.prose {
  max-width: var(--measure);
  font-size: 15px;
  line-height: 1.62;
}

.prose h3,
.prose h4,
.prose h5,
.prose h6 {
  margin: var(--s4) 0 var(--s2);
  line-height: 1.25;
}

.prose p {
  margin: 0 0 var(--s3);
}

.prose ul,
.prose ol {
  margin: 0 0 var(--s3);
  padding-left: var(--s5);
}

.prose li {
  margin-bottom: var(--s1);
}

.prose pre {
  font-family: var(--font-mono);
  font-size: 12.5px;
  background: var(--code-bg);
  border: 1px solid var(--rule-soft);
  padding: var(--s3);
  overflow-x: auto;
  margin: 0 0 var(--s3);
}

.prose code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  background: var(--code-bg);
  padding: 0 3px;
}

.prose a {
  color: var(--primary);
  text-decoration: underline;
}

.file-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.file-list li {
  display: flex;
  gap: var(--s3);
  justify-content: space-between;
  border-bottom: 1px solid var(--rule-soft);
  padding: var(--s2) 0;
  font-family: var(--font-mono);
  font-size: 12.5px;
}

/* ---------------------------------------------------------------------------
 * States: empty, error, loading, live region
 * ------------------------------------------------------------------------ */

.state {
  padding: var(--s6) var(--s4);
  max-width: var(--measure);
}

.state h2 {
  margin-bottom: var(--s2);
}

.state p {
  color: var(--muted);
}

.state-meta {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--muted);
  margin-top: var(--s3);
}

.banner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s3);
  align-items: center;
  justify-content: space-between;
  border: 1px solid var(--rule);
  border-left-width: 3px;
  border-left-color: var(--attention);
  background: var(--sheet-alt);
  color: var(--ink);
  padding: var(--s2) var(--s3);
  margin-bottom: var(--s4);
}

[aria-live='polite'],
[aria-live='assertive'] {
  border: 1px dashed var(--rule);
  background: var(--sheet-alt);
  color: var(--ink);
  padding: var(--s2) var(--s3);
  font-size: 13px;
  margin-top: var(--s3);
}

.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;
}

/* ---------------------------------------------------------------------------
 * Dialog: the only elevated surface, with focus return handled in the app
 * ------------------------------------------------------------------------ */

dialog.sheet-dialog {
  border: 1px solid var(--rule);
  border-radius: var(--radius-panel);
  background: var(--sheet);
  color: var(--ink);
  box-shadow: var(--shadow-dialog);
  padding: 0;
  max-width: 620px;
  min-width: 320px;
}

dialog.sheet-dialog::backdrop {
  background: rgba(0, 0, 0, 0.44);
}

.dialog-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s3);
  border-bottom: 1px solid var(--rule-soft);
  padding: var(--s3) var(--s4);
}

.dialog-body {
  padding: var(--s4);
}

.dialog-foot {
  display: flex;
  gap: var(--s2);
  justify-content: flex-end;
  border-top: 1px solid var(--rule-soft);
  padding: var(--s3) var(--s4);
}

.stack-sm > * + * {
  margin-top: var(--s2);
}

.stack-md > * + * {
  margin-top: var(--s4);
}

/* ---------------------------------------------------------------------------
 * Login and invite, which render without the shell
 * ------------------------------------------------------------------------ */

.gate {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--s7) var(--s4);
}

.gate-inner {
  width: 100%;
  max-width: 520px;
}

/* ---------------------------------------------------------------------------
 * Narrow layouts. Nothing is hidden; tables scroll and the rail becomes a strip.
 * ------------------------------------------------------------------------ */

@media (max-width: 900px) {
  .body-row {
    grid-template-columns: 1fr;
  }

  .rail {
    display: flex;
    gap: var(--s1);
    overflow-x: auto;
    border-right: 0;
    border-bottom: 1px solid var(--rule);
    padding: var(--s2) var(--s3);
  }

  .rail-group {
    display: none;
  }

  .nav-item {
    border-left: 0;
    border-bottom: 2px solid transparent;
    white-space: nowrap;
  }

  .nav-item[aria-current='page'] {
    border-left: 0;
    border-bottom-color: var(--accent);
  }

  .split {
    grid-template-columns: minmax(0, 1fr);
  }

  .dl {
    grid-template-columns: 1fr;
    gap: 0 0;
  }

  .dl dd {
    margin-bottom: var(--s2);
  }
}

@media (max-width: 640px) {
  .content {
    padding: var(--s4) var(--s3) var(--s7);
  }

  table.data .col-owner,
  table.data .col-when {
    display: none;
  }

  /* The top bar at a narrow width. Its five children need 421 px at their
     natural size — wordmark 58, organization picker 171, theme 160, sign out
     82, three gaps 48, padding 32 — so below 421 px the bar forced the
     document to scroll sideways and pushed Sign out past the right edge (15 px
     at 390, 45 at 360, 85 at 320). The picker was the culprit only because its
     `min-width` refused to give ground; letting it shrink alone fixed the
     scroll and left a worse defect behind, because the two BUTTONS shrank too
     and wrapped their own labels inside a 48 px bar — "Follow / system /
     theme" rendered 66 px tall in a 48 px row, clipped top and bottom.

     So the bar is allowed two rows below 640 px instead of one overfull row:
     the shell's first row becomes `auto` (a fixed 48 px row would clip the
     second line rather than grow to hold it), the controls stop shrinking and
     stop wrapping their labels, and the organization picker — whose width is
     presentational, the same name already sits in the document header on every
     screen — is the only thing that gives ground, and only when a line still
     will not fit. Nothing is hidden and no control is dropped at any width.

     `min-height` holds the bar at the 48 px DESIGN.md:146 height whenever it
     does fit on one row, so nothing changes between 641 px and 900 px. */
  .shell {
    grid-template-rows: auto 1fr;
  }

  .topbar {
    flex-wrap: wrap;
    gap: var(--s2) var(--s4);
    justify-content: flex-end;
    min-height: 48px;
  }

  .topbar > .btn,
  .topbar > .wordmark {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  /* Wordmark hard left, everything else hard right, on whichever row each
     lands: DESIGN.md:174-175 puts the selector and the account control right. */
  .topbar > .wordmark {
    margin-right: auto;
  }

  .org-picker {
    flex: 0 1 auto;
    min-width: 0;
  }

  .org-picker-field {
    min-width: 0;
  }

  .state {
    padding: var(--s5) 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}