/**
 * sources — Data Source Health. Shared primitives live in style.css.
 *
 * Everything here is scoped to `#view-sources`. Thirteen other screens inherit the same
 * stylesheet, so a rule that would be right for all of them belongs in style.css, not
 * in this file; a rule that is right only for this screen must not escape it.
 *
 * Two shared primitives were built for this screen and are used rather than replaced:
 * `.drift` with its `.warn` / `.alarm` modifiers, whose `::before` prints the severity
 * word so colour is never the only carrier, and `.alarm-row`, which puts the emphasis
 * rule down the left edge of a failing table row.
 *
 * Marking Orange (#FF3B00) appears nowhere on this screen. There is no primary action
 * and no eligibility verdict here — every state on a long list sets below 24px, so the
 * whole screen signals in Marking Ink. See the gaps file.
 */

/* --------------------------------------------------------------------------
   Head
   -------------------------------------------------------------------------- */

#view-sources .sr-head { margin-bottom: var(--lg); }
#view-sources .sr-head p.muted { max-width: 74ch; font-size: 1rem; }

/* The loader has its own line rather than a spinner, and it is driven by the
   `aria-busy` attribute `runLoader` already sets — no second source of truth. */
#view-sources .sr-loading { display: none; margin: 0; }
#view-sources[aria-busy='true'] .sr-loading { display: block; }

/* The server's own refusal states the rule; this states the remedy. */
#view-sources .sr-refusal {
  display: block;
  font-family: var(--display);
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--ink-secondary);
  margin-top: var(--xs);
}

/* --------------------------------------------------------------------------
   Plates

   A ruled sheet set down on the page ground, carrying the one permitted depth device
   in this system: a hard 3px ink registration offset with zero blur. The offset sits
   inside `main`'s own padding at every width, so it never widens the page.
   -------------------------------------------------------------------------- */

#view-sources .sr-plate {
  position: relative;
  background: var(--paper-lit);
  border: 1px solid var(--ink);
  box-shadow: 3px 3px 0 0 var(--ink);
  margin: 0 3px var(--xl) 0;
}

#view-sources .sr-plate--drift { padding: var(--md); }

#view-sources .sr-plate-title {
  margin: 0 0 var(--md);
  padding-bottom: var(--sm);
  border-bottom: 1px solid var(--rule);
  font-size: 1.0625rem;
  font-weight: 650;
  font-variation-settings: 'wdth' 112;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

#view-sources .sr-note {
  margin: var(--md) 0 0;
  padding-top: var(--sm);
  border-top: 1px solid var(--rule);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ink-secondary);
  max-width: 84ch;
}

/* Printer's furniture. Registration crosses at the four corners, drawn as rules
   rather than set as glyphs — there is no icon font anywhere in this console. */
#view-sources .sr-furniture { position: absolute; inset: 0; pointer-events: none; }
#view-sources .sr-cross { position: absolute; width: 9px; height: 9px; }
#view-sources .sr-cross::before,
#view-sources .sr-cross::after { content: ''; position: absolute; background: var(--ink); }
#view-sources .sr-cross::before { top: 50%; left: 0; width: 100%; height: 1px; }
#view-sources .sr-cross::after { top: 0; left: 50%; width: 1px; height: 100%; }
#view-sources .sr-cross--tl { top: 5px; left: 5px; }
#view-sources .sr-cross--tr { top: 5px; right: 5px; }
#view-sources .sr-cross--bl { bottom: 5px; left: 5px; }
#view-sources .sr-cross--br { bottom: 5px; right: 5px; }

/* --------------------------------------------------------------------------
   Drift signals

   Four fields on one line — severity, key, signal, detail — and the reading beneath
   them. The severity word comes from `.drift li::before` in style.css and is a grid
   item like the rest.
   -------------------------------------------------------------------------- */

#view-sources #drift { margin: 0; }
#view-sources #drift .drift { margin: 0; }
#view-sources #drift > p.ok { margin: 0; font-size: 0.9375rem; }

#view-sources .drift li {
  display: grid;
  grid-template-columns: 52px max-content max-content minmax(0, 1fr);
  grid-template-areas:
    'sev key sig detail'
    'sev reading reading reading';
  column-gap: var(--md);
  row-gap: var(--xs);
  align-items: baseline;
  padding: var(--sm) var(--md) var(--sm) var(--sm);
}
#view-sources .drift li:last-child { border-bottom: 0; }
#view-sources .drift li::before { grid-area: sev; margin-right: 0; min-width: 0; }
#view-sources .drift li strong { grid-area: key; font-weight: 600; }

#view-sources .sr-drift-signal {
  grid-area: sig;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  color: var(--ink-secondary);
  white-space: nowrap;
}

/* The detail is a sentence about a measurement, so it sets in Archivo. */
#view-sources .sr-drift-detail {
  grid-area: detail;
  font-family: var(--display);
  font-size: 0.875rem;
  line-height: 1.45;
}

#view-sources .sr-drift-reading {
  grid-area: reading;
  margin: 0;
  max-width: 82ch;
  font-family: var(--display);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ink-secondary);
}

/* --------------------------------------------------------------------------
   The source sheet
   -------------------------------------------------------------------------- */

#view-sources .sr-plate--sheet { padding: 0; }

#view-sources .sr-plate--sheet .scroller {
  margin: 0;
  border-top: 0;
}

#view-sources #sources-table { font-size: 0.875rem; }

#view-sources #sources-table thead th {
  background: var(--paper-sunk);
  border-bottom: 2px solid var(--ink);
  color: var(--ink);
  padding: 12px var(--md);
}

#view-sources #sources-table td { padding: 10px var(--md) 10px; }
#view-sources #sources-table td.num,
#view-sources #sources-table th.num { text-align: right; padding-right: var(--md); }

/* The row's bottom rule belongs under the reading, not between a row and its own
   caption — the two are one record. */
#view-sources #sources-table tbody tr.sr-row > td { border-bottom: 0; padding-bottom: var(--xs); }
#view-sources #sources-table tbody tr.sr-row > td:first-child { border-left: 2px solid var(--rule); }
/* `.alarm-row` and `tr.warn` in style.css put the emphasis rule down the left edge.
   The pinned first column is a more specific selector, so it has to restate it. */
#view-sources #sources-table tbody tr.sr-row.alarm-row > td:first-child,
#view-sources #sources-table tbody tr.sr-row.warn > td:first-child {
  border-left-color: var(--mark-ink);
}

/* The name stays put while the counts scroll under it. At 320px the first column is
   the only one that fits, so it is the one that must not move. */
#view-sources #sources-table th:first-child,
#view-sources #sources-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--paper-lit);
}
#view-sources #sources-table thead th:first-child { background: var(--paper-sunk); }

#view-sources #sources-table td.sr-src { min-width: 160px; }
#view-sources .sr-name {
  display: block;
  font-family: var(--display);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
}
#view-sources .sr-key {
  display: block;
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.02em;
  color: var(--ink-secondary);
}

/* `kind` is the schema's own controlled vocabulary — portal, soe_web, gazette_pdf,
   manual, social — so it prints exactly as the column stores it. */
#view-sources td.sr-kind,
#view-sources td.sr-lastok,
#view-sources td.sr-status { white-space: nowrap; }
#view-sources td.sr-status { text-transform: uppercase; letter-spacing: 0.06em; }

#view-sources td.sr-actions { white-space: nowrap; }
#view-sources td.sr-actions button { margin-right: var(--xs); }
#view-sources td.sr-actions button:last-child { margin-right: 0; }

#view-sources #sources-table tbody tr.sr-row:hover > td,
#view-sources #sources-table tbody tr.sr-row:hover + tr.sr-reading > td,
#view-sources #sources-table tbody tr.sr-reading:hover > td { background: var(--paper-sunk); }

/* A source that is off is a source that is not being polled. It takes the recessed
   ground and it keeps its `off` word — never a dimmed row, which reads as a rendering
   fault in bright light and says nothing to anyone who cannot see the difference. */
#view-sources #sources-table tbody tr.muted > td,
#view-sources #sources-table tbody tr.muted > td:first-child { background: var(--paper-sunk); }

/* The failure counts are the loudest thing on the screen, which is the point: a source
   that has stopped answering has to be legible at arm's length in the sun. Filled
   Marking Ink, square and ruled, still carrying its own word — `errors`, `failing`.
   Applied by class from the module rather than to `.flag-warn`, because app.js gives
   the `off` flag the same kind and `off` is a setting, not an alarm. */
#view-sources .sr-flag-loud {
  background: var(--mark-ink);
  border-color: var(--mark-ink);
  color: var(--paper-lit);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   The reading

   The screen's whole job: which failure mode this row is in, in words. A count of
   zero looks identical whether the site changed, the origin refused the handshake, or
   nobody published anything — so the row says which, or says it cannot tell.
   -------------------------------------------------------------------------- */

#view-sources #sources-table tbody tr.sr-reading > td {
  padding: 0 var(--md) 12px var(--md);
  border-left: 2px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  background: var(--paper-lit);
}
#view-sources #sources-table tbody tr.sr-reading[data-tone='alarm'] > td,
#view-sources #sources-table tbody tr.sr-reading[data-tone='warn'] > td {
  border-left-color: var(--mark-ink);
}

#view-sources .sr-reading-inner { max-width: 96ch; }

#view-sources .sr-state {
  font-family: var(--mono);
  font-size: 0.5625rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-secondary);
  margin-right: var(--sm);
  white-space: nowrap;
}
#view-sources tr.sr-reading[data-tone='alarm'] .sr-state,
#view-sources tr.sr-reading[data-tone='warn'] .sr-state {
  color: var(--mark-ink);
  font-weight: 600;
}

#view-sources .sr-reading-text {
  font-family: var(--display);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ink-secondary);
}

#view-sources tr.sr-empty > td {
  font-family: var(--display);
  font-size: 0.9375rem;
  padding: var(--lg) var(--md);
  color: var(--ink);
}

/* --------------------------------------------------------------------------
   Recent poll results

   A retry writes one sentence into `#sources-result` and the next one overwrites it.
   The line itself stays exactly where it was — it is this screen's `aria-live` region
   and nothing here duplicates it — and settled results accumulate beneath it.
   -------------------------------------------------------------------------- */

#view-sources .sr-log {
  border-top: 2px solid var(--ink);
  background: var(--paper-sunk);
  padding: var(--md);
}

#view-sources .sr-log-title {
  margin: 0 0 var(--sm);
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-secondary);
}

#view-sources .sr-log #sources-result {
  margin: 0 0 var(--sm);
  background: var(--paper-lit);
  padding: var(--sm) var(--md);
}

#view-sources .sr-log-list { list-style: none; margin: 0; padding: 0; }

#view-sources .sr-log-line {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  column-gap: var(--sm);
  align-items: baseline;
  padding: var(--xs) 0;
  border-top: 1px solid var(--rule);
}
#view-sources .sr-log-line:first-child { border-top: 0; }

#view-sources .sr-log-time {
  font-family: var(--mono);
  font-size: 0.625rem;
  color: var(--ink-secondary);
  font-variant-numeric: tabular-nums;
}

#view-sources .sr-log-key {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 600;
  margin-right: var(--xs);
}

#view-sources .sr-log-text {
  font-family: var(--display);
  font-size: 0.8125rem;
  line-height: 1.45;
}

/* The word, not only the colour. */
#view-sources .sr-log-line[data-kind='failed'] .sr-log-key,
#view-sources .sr-log-line[data-kind='failed'] .sr-log-text { color: var(--mark-ink); }
#view-sources .sr-log-line[data-kind='failed'] .sr-log-text::before {
  content: 'failed — ';
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

#view-sources .sr-log-empty {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--ink-secondary);
  max-width: 74ch;
}

/* --------------------------------------------------------------------------
   Disable confirmation

   Turning a source off is invisible from the contractor's side, so the dialog states
   the consequence and the audit trail before it asks for the reason.
   -------------------------------------------------------------------------- */

#view-sources .sr-dialog {
  width: min(460px, calc(100vw - 32px));
  padding: var(--lg) var(--md) var(--md);
  background: var(--paper-lit);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: 0;
  box-shadow: 3px 3px 0 0 var(--ink);
}
#view-sources .sr-dialog::backdrop { background: var(--ink); opacity: 0.55; }

#view-sources .sr-dialog-title {
  margin: 0 0 var(--sm);
  font-size: 1.375rem;
  font-weight: 700;
  font-variation-settings: 'wdth' 112;
}
#view-sources .sr-dialog-key { font-family: var(--mono); font-size: 1.0625rem; }

#view-sources .sr-dialog-body {
  margin: 0 0 var(--md);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--ink-secondary);
}

#view-sources .sr-dialog-label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--md);
}

#view-sources .sr-dialog-error {
  margin: calc(var(--sm) * -1) 0 var(--md);
  font-size: 0.875rem;
  color: var(--mark-ink);
  border-left: 2px solid var(--mark-ink);
  padding-left: var(--sm);
}

#view-sources .sr-dialog-actions { display: flex; gap: var(--sm); flex-wrap: wrap; }
#view-sources .sr-dialog-confirm {
  background: var(--mark-ink);
  border-color: var(--mark-ink);
  color: var(--paper-lit);
  padding: 12px 22px;
  font-size: 0.9375rem;
}
#view-sources .sr-dialog-confirm:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper-lit);
}
#view-sources .sr-dialog-cancel { padding: 12px 22px; font-size: 0.9375rem; }

/* --------------------------------------------------------------------------
   Narrow. Reviewers read this from a phone in the field, so 320px is a normal case.

   The table keeps its table semantics rather than being reflowed into blocks: the
   counts scroll sideways under a pinned first column, and the reading under each row
   says the same thing in a sentence for anyone who never scrolls.
   -------------------------------------------------------------------------- */

#view-sources .sr-scroll-hint { display: none; }

@media (max-width: 720px) {
  #view-sources .sr-plate { margin-bottom: var(--xl); }
  #view-sources .sr-plate--drift { padding: var(--sm); }

  #view-sources .sr-scroll-hint {
    display: block;
    margin: 0;
    padding: var(--sm) var(--md);
    border-bottom: 1px solid var(--rule);
    font-size: 0.8125rem;
    color: var(--ink-secondary);
  }

  #view-sources #sources-table thead th,
  #view-sources #sources-table td { padding-left: var(--sm); padding-right: var(--sm); }
  #view-sources #sources-table td.sr-src { min-width: 128px; }
  #view-sources .sr-reading-inner { max-width: 88vw; }
  #view-sources .sr-log { padding: var(--sm); }
}

@media (max-width: 560px) {
  #view-sources .drift li {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'sev' 'key' 'sig' 'detail' 'reading';
    row-gap: 2px;
  }
  #view-sources .drift li strong { justify-self: start; }
  #view-sources .sr-log-line { grid-template-columns: minmax(0, 1fr); row-gap: 2px; }
}

/* ---------------------------------------------------------------------------
   Rulesets.

   The row the matcher is actually deciding by is the one that matters, so it is
   marked structurally rather than left to be found by reading dates.
   --------------------------------------------------------------------------- */

#view-sources #ruleset-table .rs-mono {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The active ruleset carries the ink rule down its left edge. Not colour alone:
   the State column prints `active` or `superseded` in words beside it. */
#view-sources #ruleset-table tr.rs-active > td:first-child {
  border-left: 3px solid var(--ink);
  font-weight: 600;
}
#view-sources #ruleset-table tr.rs-active > td { background: var(--paper-lit); }

@media (max-width: 40rem) {
  #view-sources #ruleset-table .rs-mono { white-space: normal; }
}
