/* Per-user JWT identity harness.
 *
 * The tool is an instrument, not a dashboard: it exists so somebody can point at which hop in the
 * identity chain broke. Two rules follow from the content and drive everything here.
 *
 * 1. Colour is reserved for meaning. The ground is a cool schematic grey and text is ink navy;
 *    the only saturated values in the palette are the three verdict states. Nothing is coloured
 *    for emphasis.
 *
 * 2. An HTTP status is not a verdict. A 401 from the direct-invoke control is a PASS — it proves
 *    the gateway is not optional. Statuses therefore render neutrally and the verdict is a
 *    separate, explicit axis. Colouring 4xx red would make the harness lie about its own results.
 *
 * The data is the display type: claim values and principals are set large in mono, and the prose
 * around them is small and recessive. In this tool the string itself, and its length, is the
 * finding.
 */

:root {
  --paper:        #edf0f4;  /* cool schematic ground */
  --paper-raised: #f7f9fb;
  --ink:          #10182b;  /* near-navy, the only text colour */
  --ink-soft:     #5a6478;
  --rule:         #c3cbd8;  /* hairlines and graticule */
  --rule-faint:   #dde3ea;

  /* Verdict states. Deliberately the whole colour budget. */
  --pass:    #0f7b5a;
  --refuse:  #a8341f;
  --open:    #8a6d1f;

  --mono: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --gap: 1.5rem;
  --measure: 68ch;
}

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

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

a { color: inherit; }

/* Every interactive element keeps a visible focus ring. */
a:focus-visible,
button:focus-visible,
select:focus-visible,
input:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ── Structural labels ──────────────────────────────────────────────
 * Small caps, letterspaced, rule-coloured. Used for every label in the
 * interface so that labels never compete with data.
 */
.label {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* ── Header ─────────────────────────────────────────────────────── */

header.bar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--gap);
  flex-wrap: wrap;
  padding: 0.875rem 1.5rem;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-raised);
}

header.bar h1 {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.target {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-soft);
}

/* ── The chain rail ─────────────────────────────────────────────────
 * The five hops, always visible. This is the structural answer to the
 * project's own complaint: a failure that does not say which hop it
 * came from is the problem the harness exists to fix, so the hops are
 * never off-screen.
 */

.rail {
  display: flex;
  align-items: stretch;
  gap: 0;
  padding: 0.75rem 1.5rem 0.875rem;
  border-bottom: 1px solid var(--rule);
  overflow-x: auto;
}

.hop {
  flex: 1 1 0;
  min-width: 8.5rem;
  padding-right: 1rem;
  position: relative;
}

.hop + .hop { padding-left: 1rem; border-left: 1px solid var(--rule-faint); }

.hop-name {
  display: block;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
}

.hop-state {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.25rem;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-soft);
}

.dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  border: 1px solid currentColor;
  flex: none;
}
.dot.is-pass   { background: var(--pass);   color: var(--pass); }
.dot.is-refuse { background: var(--refuse); color: var(--refuse); }
.dot.is-open   { background: transparent;   color: var(--open); }

/* ── Sequence navigation ────────────────────────────────────────────
 * Numbered because the screens genuinely are a sequence: the claim
 * gates the strategy, which gates the call. Reading them out of order
 * makes a failure ambiguous, which is the one thing to avoid.
 */

nav.seq {
  display: flex;
  gap: 0;
  padding: 0 1.5rem;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-raised);
  overflow-x: auto;
}

nav.seq a {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.75rem 1.25rem 0.6875rem;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
}

nav.seq a:first-child { padding-left: 0; }

nav.seq .n {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-soft);
}

nav.seq .t {
  font-size: 0.8125rem;
  font-weight: 500;
}

nav.seq a[aria-current="page"] { border-bottom-color: var(--ink); }
nav.seq a[aria-current="page"] .n { color: var(--ink); }
nav.seq a:hover { background: rgba(16, 24, 43, 0.03); }

/* ── Layout ─────────────────────────────────────────────────────── */

main { padding: 2rem 1.5rem 5rem; max-width: 1180px; }

.intro { max-width: var(--measure); margin-bottom: 2rem; }
.intro h2 { margin: 0 0 0.5rem; font-size: 1.25rem; font-weight: 650; letter-spacing: -0.01em; }
.intro p  { margin: 0.5rem 0 0; color: var(--ink-soft); }

section { margin-bottom: 2.5rem; }
section > h3 {
  margin: 0 0 0.875rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
}

.panel {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  padding: 1.25rem;
}

.note {
  max-width: var(--measure);
  font-size: 0.875rem;
  color: var(--ink-soft);
  border-left: 2px solid var(--rule);
  padding-left: 0.875rem;
  margin: 1rem 0;
}

.note strong { color: var(--ink); font-weight: 600; }

/* ── Data type ──────────────────────────────────────────────────────
 * Values are set larger than the prose around them. In this tool the
 * value IS the finding.
 */

.val {
  font-family: var(--mono);
  font-size: 1rem;
  word-break: break-all;
}

.val-lg { font-family: var(--mono); font-size: 1.5rem; letter-spacing: -0.02em; word-break: break-all; }

/* ── Character ruler ────────────────────────────────────────────────
 * A graticule under a principal, with an emphasised tick at 10 — the
 * short user id limit. E1 rejects anything longer BEFORE it looks the
 * user up, with an error that never mentions length, so length is
 * worth being able to see rather than count.
 */

.ruler { display: inline-block; margin-top: 0.5rem; }

.ruler-track {
  display: flex;
  gap: 0;
  height: 0.5rem;
  border-top: 1px solid var(--rule);
}

.ruler-track i {
  display: block;
  width: 0.6ch;
  border-left: 1px solid var(--rule-faint);
  height: 0.25rem;
}

.ruler-track i:nth-child(5n) { height: 0.4rem; border-left-color: var(--rule); }

/* The boundary itself. */
.ruler-track i.limit {
  height: 0.5rem;
  border-left: 1px solid var(--open);
}

.ruler-track i.over { border-left-color: var(--refuse); }

.ruler-caption {
  display: block;
  margin-top: 0.125rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--ink-soft);
}

.ruler-caption.over { color: var(--refuse); }

/* ── Tables ─────────────────────────────────────────────────────── */

table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }

th {
  text-align: left;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: 0 0.75rem 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}

td {
  padding: 0.6rem 0.75rem 0.6rem 0;
  border-bottom: 1px solid var(--rule-faint);
  vertical-align: top;
}

td.mono, th.mono { font-family: var(--mono); }

tr.is-recommended td { background: rgba(15, 123, 90, 0.06); }

/* ── Verdict, kept separate from status ─────────────────────────── */

.status {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink);
}

.verdict {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.15rem 0.5rem;
  border: 1px solid currentColor;
}

.verdict.is-pass   { color: var(--pass); }
.verdict.is-refuse { color: var(--refuse); }
.verdict.is-open   { color: var(--open); }

.badge {
  font-family: var(--mono);
  font-size: 0.6875rem;
  padding: 0.05rem 0.35rem;
  border: 1px solid var(--rule);
  color: var(--ink-soft);
  white-space: nowrap;
}

/* ── Forms ──────────────────────────────────────────────────────── */

form.controls { display: flex; flex-wrap: wrap; gap: 1.25rem; align-items: flex-end; }

.field { display: flex; flex-direction: column; gap: 0.35rem; }

select, input[type="text"] {
  font-family: var(--mono);
  font-size: 0.875rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--rule);
  background: var(--paper-raised);
  color: var(--ink);
  min-width: 14rem;
}

.check { display: flex; align-items: center; gap: 0.45rem; font-size: 0.8125rem; }

button {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.55rem 1.1rem;
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper-raised);
  cursor: pointer;
}

button:hover { background: transparent; color: var(--ink); }

button.quiet { background: transparent; color: var(--ink); }
button.quiet:hover { background: var(--ink); color: var(--paper-raised); }

/* ── Sign in ────────────────────────────────────────────────────── */

.signin { max-width: 34rem; margin: 5rem auto; padding: 0 1.5rem; }
.signin h2 { font-size: 1.5rem; margin: 0 0 0.75rem; letter-spacing: -0.02em; }
.signin p { color: var(--ink-soft); }
.signin .chain {
  font-family: var(--mono);
  font-size: 0.8125rem;
  line-height: 2;
  margin: 1.75rem 0;
  padding: 1rem 1.25rem;
  border: 1px solid var(--rule);
  background: var(--paper-raised);
}

/* ── Results ────────────────────────────────────────────────────── */

.result { border: 1px solid var(--rule); background: var(--paper-raised); margin-bottom: 1rem; }

.result-head {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  flex-wrap: wrap;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--rule-faint);
}

.result-head .name { font-weight: 600; font-size: 0.9375rem; }
.result-head .when { font-family: var(--mono); font-size: 0.75rem; color: var(--ink-soft); margin-left: auto; }

.result-body { padding: 1rem; }

.hint {
  font-size: 0.875rem;
  border-left: 2px solid var(--open);
  padding-left: 0.875rem;
  margin: 0 0 1rem;
  max-width: var(--measure);
}

pre {
  font-family: var(--mono);
  font-size: 0.78125rem;
  line-height: 1.5;
  background: var(--paper);
  border: 1px solid var(--rule-faint);
  padding: 0.875rem;
  overflow-x: auto;
  margin: 0.5rem 0 0;
}

details summary { cursor: pointer; font-size: 0.8125rem; color: var(--ink-soft); }
details[open] summary { margin-bottom: 0.5rem; }

.empty { color: var(--ink-soft); font-size: 0.9375rem; }

/* ── Responsive ─────────────────────────────────────────────────── */

@media (max-width: 720px) {
  main { padding: 1.5rem 1rem 4rem; }
  header.bar, .rail, nav.seq { padding-left: 1rem; padding-right: 1rem; }
  .hop { min-width: 7rem; }
  .val-lg { font-size: 1.125rem; }
  form.controls { flex-direction: column; align-items: stretch; }
  select, input[type="text"] { min-width: 0; width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
