/*
 * The operator UI (Phase 3 §10.3).
 *
 * Business-professional: restrained, high-contrast, no ornament. This is a screen where someone
 * revokes production access at 2am; it should be legible, not characterful.
 *
 * Hand-written, with no build step, because Alpine was chosen precisely so the UI drops in from
 * one local script tag - pairing it with a toolchain that needs `npm run build` would throw
 * away the reason for choosing it (§10.1).
 *
 * Every colour is a custom property declared once and overridden for dark, so a token is
 * defined in one place and both themes get it. Both are checked against WCAG AA by computation
 * in test_contrast.py, not by eye: dark mode is where this quietly fails, because grey-on-grey
 * looks fine to whoever picked it on a good monitor.
 */

:root {
  --surface: #ffffff;
  --surface-raised: #f6f7f9;
  --text: #111418;
  --muted: #4a535e;
  --line: #858e98;
  --accent: #10508c;
  --accent-text: #ffffff;
  --danger: #a3231d;
  --danger-surface: #fdf1f0;
  --ok: #1c6b3f;

  /* Phase 4 §7: something is about to stop working, which is neither an error nor fine.
     Amber rather than a second red, so a screen showing both says two different things. */
  --warn: #8a5200;

  --radius: 4px;
  --gap: 1rem;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

:root[data-theme="dark"] {
  --surface: #14171a;
  --surface-raised: #1d2126;
  --text: #e8eaed;
  --muted: #a8b1bb;
  --line: #646e7a;
  --accent: #7cb6ea;
  --accent-text: #0b0d0f;
  --danger: #f08b85;
  --danger-surface: #2a1a19;
  --ok: #79d39f;
  --warn: #e8b552;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  background: var(--surface);
}

a { color: var(--accent); }

code, .mono { font-family: var(--mono); font-size: 0.9em; }

.masthead {
  display: flex;
  align-items: center;
  gap: var(--gap);
  padding: 0.75rem 1.25rem;
  border-bottom: 1px solid var(--line);
  background: var(--surface-raised);
}

.masthead h1 { font-size: 1rem; margin: 0; font-weight: 600; }

.masthead nav { display: flex; gap: 1rem; flex: 1; }

.masthead nav a { text-decoration: none; color: var(--muted); }
.masthead nav a[aria-current="page"] { color: var(--text); font-weight: 600; }

main { padding: 1.5rem 1.25rem; max-width: 68rem; }

h2 { font-size: 1.15rem; margin: 0 0 0.75rem; }

table { border-collapse: collapse; width: 100%; }

th, td {
  text-align: left;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

th { color: var(--muted); font-weight: 600; font-size: 0.85rem; }

tbody tr:hover { background: var(--surface-raised); }

.grant-group {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
  margin-bottom: var(--gap);
  background: var(--surface);
}

/*
 * §10.4: the three grant lists must look like three things.
 *
 * §6.1's whole point is that grants, bind_grants and dynamic_grants are separate privileges and
 * none implies another. Rendering them as three identically-styled boxes in a row teaches the
 * operator the opposite of the model, so each carries its own label and its own statement of
 * what it confers - and the bind group is marked out further, because it is the one that makes
 * the bastion open a listening port.
 */
.grant-group > h3 { margin: 0 0 0.2rem; font-size: 0.95rem; }
.grant-group > .confers { margin: 0 0 0.6rem; color: var(--muted); font-size: 0.85rem; }
.grant-group--bind { border-left: 3px solid var(--danger); }
.grant-group--bind .confers { color: var(--danger); font-weight: 600; }

.pill {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-size: 0.78rem;
  border: 1px solid var(--line);
  color: var(--muted);
}

.pill--revoked { color: var(--danger); border-color: var(--danger); }
.pill--active { color: var(--ok); border-color: var(--ok); }
.pill--warn { color: var(--warn); border-color: var(--warn); }

/* A tab that has something behind it. Weight as well as colour, because colour alone is not a
   signal for everyone reading this. */
.button--warn { color: var(--warn); border-color: var(--warn); font-weight: 600; }

.problems {
  border: 1px solid var(--danger);
  background: var(--danger-surface);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin-bottom: var(--gap);
}

.problems ul { margin: 0.4rem 0 0; padding-left: 1.1rem; }
.problems li { color: var(--danger); }

button, .button {
  font: inherit;
  padding: 0.35rem 0.8rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface-raised);
  color: var(--text);
  cursor: pointer;
}

button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

input[type="text"], input[type="search"], input[type="file"], select {
  font: inherit;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}

.filter-bar { display: flex; gap: 0.6rem; align-items: center; margin-bottom: var(--gap); }

.empty { color: var(--muted); font-style: italic; }

/*
 * Grant sync's per-row port controls on the identity screen. Classes rather than style=
 * attributes because the CSP is style-src 'self' (security.py): an inline style attribute is
 * dropped by the browser, and a form that is meant to sit inline falls onto its own line
 * without anything failing loudly.
 */
.inline-form { display: inline; }
.port-input { width: 6.5em; }

.truncate { max-width: 22rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/*
 * §10.5's one-time reveal.
 *
 * Deliberately unmissable: this is the only moment the token exists, and an operator who
 * scrolls past it has lost it. Not styled as a success message, because a success message is
 * the thing people learn to dismiss without reading.
 */
.reveal {
  border: 2px solid var(--accent);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin-bottom: var(--gap);
  background: var(--surface-raised);
}

.reveal h3 { margin: 0 0 0.5rem; }

.reveal__value {
  font-family: var(--mono);
  font-size: 1.05rem;
  word-break: break-all;
  user-select: all;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

label { font-weight: 600; font-size: 0.9rem; }

textarea {
  font: inherit;
  font-family: var(--mono);
  width: 100%;
  max-width: 40rem;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
}
