/*
 * WhatHasChanged — application stylesheet.
 *
 * Derived from designs/src/mockup.css, with three deliberate departures from it:
 *
 *   1. No fixed 1440px width and no fake browser chrome. The mockups are
 *      screenshot targets; this is the real thing.
 *   2. Real interaction states (:hover, :focus-visible, [disabled], [aria-current])
 *      instead of the .on / .active classes the mockups painted by hand.
 *   3. Every rule that the mockups expressed as a style="" attribute is a class
 *      here. That is not tidiness: the CSP is `style-src 'self'` with no
 *      unsafe-inline (src/index.ts), which BLOCKS inline style attributes. A
 *      style="" copied over from a mockup would silently not apply.
 *
 * Colours are the mockup palette unchanged, so the built UI and the approved
 * designs still read as the same product.
 */

*,
*::before,
*::after {
  box-sizing: border-box;
}

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

body {
  font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif;
  background: #eef0f3;
  color: #1f2933;
  font-size: 13px;
  line-height: 1.45;
}

a {
  color: #2d5385;
}

/* A visible focus ring everywhere. The register is used by keyboard for long
   stretches — filter, tab, sort, page — and an invisible focus position is the
   fastest way to make that unusable. */
:focus-visible {
  outline: 2px solid #2d5385;
  outline-offset: 2px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.hidden {
  display: none !important;
}

/* ---------- app header ---------- */
header.app {
  background: #1f3a5f;
  color: #fff;
  padding: 0 24px;
  display: flex;
  align-items: center;
  min-height: 56px;
  gap: 24px;
  flex-wrap: wrap;
}

header.app .brand {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.2px;
}

header.app .brand span {
  opacity: 0.55;
  font-weight: 400;
  font-size: 12px;
  margin-left: 8px;
}

header.app nav {
  display: flex;
  gap: 4px;
  flex: 1;
}

header.app nav a {
  color: #c5d3e5;
  text-decoration: none;
  padding: 8px 14px;
  border-radius: 4px;
  font-size: 13px;
}

header.app nav a:hover {
  background: #2a4a76;
  color: #fff;
}

header.app nav a[aria-current='page'] {
  background: #2d5385;
  color: #fff;
  font-weight: 600;
}

.who {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
}

.who .avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #4a76b0;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 11px;
}

/* The role pill is decoration. Every authorization decision is made server-side
   from the token (SEC-3); this only tells the user what to expect. */
.pill-role {
  background: #2d5385;
  padding: 3px 9px;
  border-radius: 10px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: 600;
}

.pill-role.admin {
  background: #7b3f9d;
}

/* ---------- layout ---------- */
main {
  padding: 20px 24px 40px;
  max-width: 1600px;
  margin: 0 auto;
}

main.centred {
  max-width: 520px;
  margin: 80px auto;
  text-align: center;
}

main.centred h1 {
  font-size: 19px;
  margin: 0 0 14px;
}

main.centred p {
  color: #4a5560;
  margin: 0 0 12px;
}

.crumb {
  font-size: 11px;
  color: #6b7684;
  margin-bottom: 10px;
}

h1.view {
  font-size: 21px;
  font-weight: 600;
  margin: 0 0 4px;
}

.sub {
  color: #6b7684;
  font-size: 12px;
  margin-bottom: 18px;
}

.card {
  background: #fff;
  border: 1px solid #dbe0e6;
  border-radius: 6px;
}

.card + .card {
  margin-top: 16px;
}

.card > h2 {
  font-size: 13px;
  font-weight: 600;
  padding: 12px 16px;
  margin: 0;
  border-bottom: 1px solid #e6eaef;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.card .body {
  padding: 16px;
}

/* ---------- search + filters ---------- */
.searchrow {
  display: flex;
  gap: 10px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.searchbox {
  flex: 1;
  min-width: 260px;
  display: flex;
  align-items: center;
  gap: 9px;
  background: #fff;
  border: 2px solid #2d5385;
  border-radius: 5px;
  padding: 7px 13px;
}

.searchbox .ico {
  color: #6b7684;
  font-size: 14px;
}

.searchbox input {
  flex: 1;
  border: 0;
  font-size: 14px;
  outline: none;
  color: #1f2933;
  font-family: inherit;
  background: transparent;
}

.btn {
  border: 1px solid #c8ced6;
  background: #fff;
  border-radius: 5px;
  padding: 8px 15px;
  font-size: 13px;
  cursor: pointer;
  color: #1f2933;
  white-space: nowrap;
  font-family: inherit;
}

.btn:hover:not([disabled]) {
  background: #f6f8fa;
}

.btn[disabled] {
  color: #a8b0ba;
  cursor: default;
}

.btn.primary {
  background: #2d5385;
  border-color: #2d5385;
  color: #fff;
  font-weight: 600;
}

.btn.primary:hover:not([disabled]) {
  background: #35608f;
}

.btn.sm {
  padding: 5px 10px;
  font-size: 12px;
}

/*
 * Outlined rather than filled red. `.primary` is filled because it is the expected
 * action on its screen; suppression is the exception on a sealed record, and a solid
 * red block reads as the thing to click. It also keeps this visually distinct from a
 * delete button, which is what it is deliberately not (FR-9, ST-10).
 */
.btn.danger {
  background: #fff;
  border-color: #c0392b;
  color: #c0392b;
}

.btn.danger:hover:not([disabled]) {
  background: #fdecea;
}

.filters {
  background: #fff;
  border: 1px solid #dbe0e6;
  border-radius: 6px;
  padding: 13px 16px;
  margin-bottom: 14px;
}

.filters .line {
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
  align-items: center;
}

.filters .line + .line {
  margin-top: 10px;
  border-top: 1px solid #eef1f4;
  padding-top: 11px;
}

.facet {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: #6b7684;
}

select,
input[type='date'],
input[type='text'] {
  border: 1px solid #c8ced6;
  border-radius: 4px;
  padding: 6px 9px;
  font-size: 12px;
  font-family: inherit;
  color: #1f2933;
  background: #fff;
}

select:hover {
  border-color: #98a2ad;
}

.chips {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  align-items: center;
}

.chipcount {
  font-size: 11px;
  color: #6b7684;
}

/* Chips are how the restored state is made visible WITHOUT a banner. SR-14.7
   requires restoration to be silent; the chips and the exact result count are
   what tell the user which filters are in force. */
.chip {
  background: #eaf1f9;
  border: 1px solid #b8cde5;
  color: #1f3a5f;
  border-radius: 12px;
  padding: 3px 5px 3px 11px;
  font-size: 11px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.chip button {
  border: 0;
  background: transparent;
  color: #6b8bb5;
  font-weight: 700;
  cursor: pointer;
  font-size: 12px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 8px;
  font-family: inherit;
}

.chip button:hover {
  background: #d6e4f4;
  color: #1f3a5f;
}

.linkbtn {
  border: 0;
  background: transparent;
  font-size: 11px;
  color: #2d5385;
  text-decoration: underline;
  cursor: pointer;
  font-family: inherit;
  padding: 0;
}

.spacer {
  flex: 1;
}

/* ---------- tables ---------- */
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

thead th {
  text-align: left;
  padding: 0;
  background: #f6f8fa;
  border-bottom: 1px solid #dbe0e6;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: #57616d;
  font-weight: 600;
}

thead th .colhead {
  padding: 10px 12px;
}

/* A sortable header is a button, not a div with a click handler: it has to be
   reachable by keyboard and announce itself as pressable. */
thead th button.colhead {
  border: 0;
  background: transparent;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  cursor: pointer;
  width: 100%;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 5px;
}

thead th button.colhead:hover {
  color: #1f3a5f;
  background: #eef2f6;
}

thead th[aria-sort] button.colhead {
  color: #1f3a5f;
}

thead th .sortmark {
  color: #2d5385;
  font-size: 9px;
}

tbody td {
  padding: 10px 12px;
  border-bottom: 1px solid #eef1f4;
  vertical-align: top;
}

tbody tr.group:hover td {
  background: #f8fafc;
}

tbody tr.child td {
  background: #fbfcfd;
  font-size: 11.5px;
  color: #4a5560;
}

tbody tr.child td:first-child {
  padding-left: 34px;
}

/* Suppressed rows stay visible, struck through, with the reason inline —
   ST-3/ST-4. They are never filtered out: suppression is a label, not a
   soft delete. */
tbody tr.suppressed td {
  color: #98a2ad;
}

tbody tr.suppressed .gname {
  text-decoration: line-through;
}

.gname {
  font-weight: 600;
  color: #1f3a5f;
}

.rowlink {
  border: 0;
  background: transparent;
  font: inherit;
  font-weight: 600;
  color: #1f3a5f;
  cursor: pointer;
  padding: 0;
  text-align: left;
}

.rowlink:hover {
  text-decoration: underline;
}

.mono {
  font-family: Consolas, 'SFMono-Regular', monospace;
  font-size: 11px;
}

.ref {
  color: #6b7684;
  font-size: 10px;
  font-family: Consolas, 'SFMono-Regular', monospace;
}

.reason-supp {
  color: #c0392b;
}

.expander {
  border: 0;
  background: transparent;
  color: #6b7684;
  font-size: 10px;
  cursor: pointer;
  padding: 2px 5px;
  border-radius: 3px;
  font-family: inherit;
}

.expander:hover {
  background: #e6eaef;
  color: #1f2933;
}

.tag {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 3px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
}

/* Production tinting comes from the `is_production` flag carried on the facet
   payload, NOT from a hard-coded list of environment names (ENV-9) — so adding
   an environment later needs no CSS change. */
.tag.env {
  background: #eef3f8;
  color: #3d5a80;
  border: 1px solid #c5d5e5;
}

.tag.env.prod {
  background: #fdecea;
  color: #a3271b;
  border-color: #f0b8b0;
}

.tag.dept {
  background: #f2f4f7;
  color: #4a5560;
  border: 1px solid #dbe0e6;
}

.tag.sealed,
.tag.ok {
  background: #e8f5e9;
  color: #1b5e20;
  border: 1px solid #b5d8b8;
}

.tag.supp {
  background: #f0f1f3;
  color: #6b7684;
  border: 1px solid #d5d9de;
}

.flagself {
  color: #b8860b;
  font-size: 11px;
}

/*
 * OWN-7 — "recorded on behalf of someone else".
 *
 * A DIFFERENT colour from .flagself, deliberately. The two marks sit next to each other
 * on a group row and mean different things with different remedies: one says a change
 * went in without a second pair of eyes, the other says the person who typed it is not
 * the person named as having done it. Rendered identically they would blur into a
 * generic "unusual", which is the state of knowing that something is wrong without
 * knowing what.
 *
 * Slate blue rather than a second warning colour, because this is NOT a warning.
 * Recording a vendor's or a colleague's work is legitimate and expected; the mark exists
 * so it is countable, and red would tell every reader that a permitted act is a fault.
 *
 * Applied to a <td> as well as to a <span>, so `color` and not `background` — a td that
 * changed colour would read as an error cell.
 */
.flagentered {
  color: #4a6fa5;
  font-size: 11px;
}

/*
 * OWN-6 — the marker on an attribution recovered from the audit log rather than stored.
 *
 * Muted further than .ref, which is already the quiet class. This is a footnote on a
 * value, not a value: it must be readable by anyone who wonders where the name came
 * from, and invisible to everyone who does not.
 */
.derived {
  color: #8b95a1;
  font-style: italic;
}

/* ---------- pagination ---------- */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 16px;
  border-top: 1px solid #e6eaef;
  font-size: 12px;
  color: #57616d;
  gap: 12px;
  flex-wrap: wrap;
}

.pager .nums {
  display: flex;
  gap: 4px;
  align-items: center;
}

.pgbtn {
  min-width: 30px;
  height: 30px;
  border: 1px solid #c8ced6;
  border-radius: 4px;
  background: #fff;
  font-size: 12px;
  padding: 0 8px;
  cursor: pointer;
  font-family: inherit;
  color: #1f2933;
}

.pgbtn:hover:not([disabled]):not([aria-current='true']) {
  background: #f0f4f8;
}

.pgbtn[aria-current='true'] {
  background: #2d5385;
  border-color: #2d5385;
  color: #fff;
  font-weight: 600;
}

.pgbtn[disabled] {
  color: #b6bcc6;
  cursor: default;
}

.pgdots {
  color: #98a2ad;
  padding: 0 3px;
}

/* ---------- detail view ---------- */
/* The heading and the Admin actions on one line, as the mockups drew them. */
.detailhead {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  margin-bottom: 14px;
}

.detailhead .grow {
  flex: 1;
}

.actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

/*
 * The status form reuses `.facet` and `.line` from the filter panel, which are scoped
 * to `.filters` there. These two rules give them the same layout inside a card.
 */
.card .body .facet {
  margin-bottom: 11px;
}

.card .body .line {
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 14px;
}

.card .body input.grow {
  flex: 1;
  min-width: 280px;
}

.kv {
  display: grid;
  grid-template-columns: 170px 1fr;
  gap: 8px 16px;
  font-size: 12px;
  margin: 0;
}

.kv dt {
  color: #6b7684;
}

.kv dd {
  color: #1f2933;
  margin: 0;
}

.evidence {
  font-family: Consolas, 'SFMono-Regular', monospace;
  font-size: 11px;
  word-break: break-all;
}

/* ---------- service tokens ---------- */
/*
 * The one card in this application that shows a credential — API-2. Deliberately loud:
 * it appears once, and an operator who mistakes it for an ordinary confirmation loses
 * the only copy.
 */
.card.minted {
  border: 2px solid #b8860b;
}

/*
 * The token itself. Larger than .evidence and selectable in one gesture, because the
 * fallback when the clipboard API is unavailable is the user selecting it by hand — and
 * `user-select: all` turns that into a single click instead of a drag across 51
 * characters where a missed one produces a token that fails authentication for no
 * visible reason.
 */
.tokenvalue {
  font-size: 13px;
  padding: 11px 13px;
  margin: 0 0 12px;
  background: #f7f8fa;
  border: 1px solid #d5d9de;
  border-radius: 4px;
  user-select: all;
}

/* ---------- banners ---------- */
/*
 * Used for FAILURES and for the delivery outcome of a submission, never for
 * "your preferences were restored" — SR-14.7 makes restoration silent, and this
 * was decided rather than defaulted (see designs/README.md).
 */
.banner {
  border-radius: 5px;
  padding: 12px 15px;
  font-size: 12px;
  display: flex;
  gap: 11px;
  align-items: flex-start;
  margin-bottom: 16px;
}

.banner.warn {
  background: #fff8e6;
  border: 1px solid #f0d9a8;
  color: #6b4e00;
}

.banner.err {
  background: #fdecea;
  border: 1px solid #f0b8b0;
  color: #8a1f13;
}

.banner.info {
  background: #eaf1f9;
  border: 1px solid #b8cde5;
  color: #1f3a5f;
}

.banner b {
  font-weight: 600;
}

.empty {
  padding: 34px 16px;
  text-align: center;
  color: #6b7684;
  font-size: 12.5px;
}

.note {
  font-size: 10.5px;
  color: #6b7684;
  font-style: italic;
  padding: 9px 16px;
  border-top: 1px dashed #dbe0e6;
  background: #fafbfc;
}

.busy {
  color: #6b7684;
  font-size: 12px;
  padding: 30px 0;
  text-align: center;
}
