/* The dashboard, in Operity's own register (M9).
 *
 * Tokens, type, corners, capsules and easings are the marketing site's, so
 * moving from operity.co into the product is one brand and not two. Nothing is
 * fetched from anywhere: the Content-Security-Policy on /app admits this
 * origin only, and the typeface is the system stack — San Francisco on Apple
 * devices, whatever the machine has elsewhere. No build step, no dependency.
 *
 * Motion is iOS-like and quiet, and all of it is off under prefers-reduced-
 * motion: the rule at the foot of this file stops every animation and
 * transition, and app.js reads the same preference before it counts a figure
 * up rather than simply printing it.
 */

:root {
  --ground: #0a0a0a;
  --raised: #121212;
  --rule: rgba(255, 255, 255, 0.1);
  --rule-strong: rgba(255, 255, 255, 0.24);
  --ink: #f2f2f2;
  --body: #bdbdbd;
  --muted: #8a8a8a;
  --signal: #d7ff3f;
  --refuse: #e2705c;
  /* A deadline coming up. Warm, not alarming: coral is a refusal and
     nothing else, so it is kept for a job that is actually overdue. */
  --warn: #e8c15a;

  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
    "Helvetica Neue", system-ui, sans-serif;

  --shell: 74rem;
  --gutter: clamp(20px, 4vw, 48px);

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* springs sampled from a damped oscillator — the way iOS moves */
  --spring: linear(0, 0.0355, 0.122, 0.2354, 0.3583, 0.4793, 0.5909, 0.6893, 0.7727,
    0.841, 0.8951, 0.9366, 0.9673, 0.9891, 1.0037, 1.0128, 1.0177, 1.0197, 1.0197,
    1.0184, 1.0163, 1.0139, 1.0115, 1.0091, 1.0071, 1.0053, 1.0038, 1.0026, 1.0016,
    1.0009, 1.0004, 1);
  --snappy: linear(0, 0.0441, 0.1514, 0.2907, 0.4392, 0.5815, 0.708, 0.8139, 0.8978,
    0.9605, 1.0043, 1.0323, 1.0478, 1.0538, 1.0533, 1.0486, 1.0416, 1.0336, 1.0256,
    1.0184, 1.0122, 1.0072, 1.0033, 1.0006, 0.9987, 0.9977, 0.9972, 0.9976, 1);
  color-scheme: dark;
}

* { box-sizing: border-box; }

/* An element's own `display` would otherwise override the hidden attribute. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font: 16px/1.6 var(--font);
  letter-spacing: -0.011em;
  color: var(--body);
  background: var(--ground);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
::selection { background: var(--signal); color: var(--ground); }
:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; }

h1, h2, p { margin: 0; }

.skip {
  position: absolute; left: 12px; top: -60px; z-index: 60;
  padding: 10px 16px; border-radius: 999px;
  background: var(--signal); color: var(--ground);
  font-size: 15px; font-weight: 600; text-decoration: none;
  transition: top 160ms var(--ease-out);
}
.skip:focus { top: 12px; }

/* ---------- the bar ---------- */
.bar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 26px;
  padding: 0 var(--gutter);
  min-height: 64px;
  border-bottom: 1px solid var(--rule);
  background: rgba(10, 10, 10, 0.72);
  -webkit-backdrop-filter: blur(18px) saturate(170%);
  backdrop-filter: blur(18px) saturate(170%);
}
.brand {
  color: var(--ink);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.04em;
  text-decoration: none;
}

nav { display: flex; gap: 22px; align-items: center; flex-wrap: wrap; }
a { color: var(--ink); }
/* The documentation link sits OUTSIDE nav on purpose: nav is hidden until you
   are signed in, and a signed-out visitor must still have a way to the docs.
   A test asserts exactly that, so moving it inside nav will fail the suite. */
nav a, .bar > a:not(.brand) {
  position: relative;
  padding-block: 6px;
  color: var(--muted);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.012em;
  text-decoration: none;
  transition: color 200ms var(--ease-out);
}
nav a::after, .bar > a:not(.brand)::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 1.5px;
  border-radius: 2px;
  background: var(--signal);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 420ms var(--snappy);
}
nav a:hover, .bar > a:not(.brand):hover { color: var(--ink); }
nav a:hover::after, .bar > a:not(.brand):hover::after { transform: scaleX(1); }

#account { margin-left: auto; display: flex; gap: 10px; align-items: center; color: var(--muted); }
#who { font-size: 14.5px; }
#account-status { font-size: 14px; }

.notice {
  padding: 10px var(--gutter);
  color: var(--muted);
  font-size: 14px;
  border-bottom: 1px solid var(--rule);
}

main, [data-view] { max-width: var(--shell); margin: 0 auto; padding: 22px var(--gutter) 96px; }

[data-view="keys"] {
  border-radius: 22px;
  background: linear-gradient(180deg, #161616 0%, #0f0f0f 100%);
  box-shadow: inset 0 0 0 1px var(--rule), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  margin: 18px auto;
  padding: 26px clamp(20px, 3vw, 32px);
}

h1 {
  color: var(--ink);
  font-size: clamp(32px, 4.2vw, 50px);
  font-weight: 600;
  letter-spacing: -0.034em;
  line-height: 1.04;
  margin-bottom: 18px;
}
h2 {
  color: var(--ink);
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.018em;
  margin: 34px 0 12px;
}

/* ---------- money ----------
 * Amounts are tabular, the whole part right-aligned against the decimal point
 * and the fraction hanging off it, so a column of them lines up on the point
 * however many places each one carries.
 */
.money {
  display: inline-flex;
  align-items: baseline;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -0.02em;
}
.money-int { text-align: right; }
.money-frac { min-width: 3.1ch; text-align: left; color: var(--muted); font-size: 0.78em; }
.is-zero .money-int { color: var(--muted); }

/* ---------- tables (ledger, jobs, keys, health) ---------- */
table { width: 100%; border-collapse: collapse; display: block; overflow-x: auto; }
th, td {
  text-align: left;
  padding: 10px 18px 10px 0;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
th { font-size: 13px; color: var(--muted); font-weight: 500; }
td { color: var(--body); font-size: 15px; }

dl { display: grid; grid-template-columns: minmax(10rem, max-content) 1fr; gap: 8px 28px; }
dt { color: var(--muted); font-size: 14.5px; }
dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }

label { display: flex; flex-direction: column; gap: 6px; font-size: 14px; color: var(--muted); }

input, select {
  font: inherit;
  /* 16px is a floor, not a preference: iOS Safari zooms the whole page when a
     field smaller than that takes focus, and the first field anybody touches on
     a phone is the sign-in box. Every override below holds the floor too. */
  font-size: 16px;
  padding: 11px 13px;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--raised);
  color: var(--ink);
  transition: border-color 200ms var(--ease-out);
}
input:hover, select:hover { border-color: var(--rule-strong); }
/* The global :focus-visible ring is the product's focus indicator; this rule
   used to remove the outline and leave a 1px border colour change as the only
   sign of where a keyboard user was — and in the ledger's date sheet, which has
   its own border, no sign at all. The border still lights; the ring stays. */
input:focus, select:focus { border-color: var(--signal); }
input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--signal); padding: 0; }

/* ---------- iOS capsules ---------- */
button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 38px;
  padding-inline: 17px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  box-shadow: inset 0 0 0 1px var(--rule-strong);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.012em;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background 220ms var(--ease-out), box-shadow 220ms var(--ease-out),
    transform 520ms var(--snappy);
  -webkit-tap-highlight-color: transparent;
}
button:hover, .btn:hover {
  background: rgba(255, 255, 255, 0.11);
  box-shadow: inset 0 0 0 1px rgba(215, 255, 63, 0.45);
}
button:active, .btn:active { transform: scale(0.955); transition: transform 110ms ease-out; }
button:disabled { opacity: 0.45; pointer-events: none; }
button.danger { color: var(--refuse); }
button.danger:hover { box-shadow: inset 0 0 0 1px rgba(226, 112, 92, 0.5); }

.btn-primary {
  background: linear-gradient(180deg, #e6ff7d 0%, var(--signal) 52%, #c7f02f 100%);
  color: var(--ground);
  font-weight: 600;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45);
}
.btn-primary:hover {
  background: linear-gradient(180deg, #f0ff9e 0%, #e3ff72 52%, #d2f748 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55), 0 12px 28px -16px rgba(215, 255, 63, 0.5);
}

.once {
  border-radius: 18px;
  background: rgba(215, 255, 63, 0.06);
  box-shadow: inset 0 0 0 1px rgba(215, 255, 63, 0.4);
  padding: 16px 18px;
  margin: 16px 0;
}
.once p { margin-bottom: 10px; }
pre {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 13px;
  color: var(--ink);
  background: var(--raised);
  border-radius: 12px;
  padding: 12px 14px;
}

.caveat { border-left: 2px solid var(--signal); padding-left: 14px; color: var(--body); }
.hint { color: var(--muted); font-size: 14.5px; max-width: 72ch; margin-top: 22px; }
.rule { border-left: 2px solid var(--signal); padding-left: 14px; }

/* Every failure says something (2026-09-17); empty, the line takes no space. */
.problem { color: var(--refuse); margin: 12px 0; max-width: 68ch; }
.problem:empty { display: none; }

/* =======================================================================
 * The agents screen (M9)
 * ======================================================================= */

.summary { margin-bottom: 34px; }
.sum-k { color: var(--muted); font-size: 14.5px; }
.sum-total {
  color: var(--ink);
  font-size: clamp(44px, 6.4vw, 84px);
  font-weight: 600;
  letter-spacing: -0.038em;
  line-height: 1.02;
  margin-top: 4px;
}
.sum-total .money-frac { font-size: 0.4em; min-width: 3.2ch; }

.figures { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 18px; }
.fig {
  position: relative;
  overflow: hidden;
  flex: 1 1 200px;
  border-radius: 18px;
  padding: 15px 18px 16px;
  background: linear-gradient(180deg, #161616 0%, #0f0f0f 100%);
  box-shadow: inset 0 0 0 1px var(--rule), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  animation: rise 560ms var(--spring) backwards;
}
.fig::before {
  content: "";
  position: absolute;
  inset-inline: 14%;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(215, 255, 63, 0.3), transparent);
}
.fig .k { display: block; color: var(--muted); font-size: 13.5px; }
.fig .v {
  display: block;
  margin-top: 5px;
  color: var(--ink);
  font-size: 23px;
  font-weight: 600;
  letter-spacing: -0.026em;
  font-variant-numeric: tabular-nums;
}
.fig .v .money-frac { font-size: 0.62em; }
.fig .sub { display: block; margin-top: 3px; color: var(--muted); font-size: 13px; }

/* the capsule: how the held total is split, coloured by what each agent is */
.alloc { display: flex; gap: 3px; height: 10px; margin-top: 22px; }
.alloc span {
  display: block;
  height: 100%;
  border-radius: 999px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 700ms var(--ease-out), filter 200ms var(--ease-out);
}
.alloc .is-grown { transform: scaleX(1); }
.alloc .is-lit { filter: brightness(1.6); }
.st-active { background: var(--signal); }
.st-exhausted { background: rgba(255, 255, 255, 0.34); }
.st-suspended { background: var(--refuse); }
.st-retired { background: rgba(255, 255, 255, 0.14); }

#agents-share { margin-top: 14px; }
#agents-share th, #agents-share td { border-bottom: 1px solid rgba(255, 255, 255, 0.055); }
#agents-share tr[data-agent] { animation: rise 520ms var(--spring) backwards; }
#agents-share tr[data-agent]:hover td { background: rgba(255, 255, 255, 0.03); color: var(--ink); }
.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 10px;
  vertical-align: 1px;
}
.share-handle { color: var(--ink); }
.share-num { font-variant-numeric: tabular-nums; }
.share-state { color: var(--muted); }
.share-state.is-suspended { color: var(--refuse); }
/* the legend is a block under the capsule, not a full-width table */
#agents-share { max-width: 46rem; }
#agents-share th:not(:first-child), #agents-share td:not(:first-child) { text-align: right; }
#agents-share th:last-child, #agents-share td:last-child { padding-right: 0; }
#agents-share td:last-child .money { justify-content: flex-end; }

/* ---------- the cards ---------- */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}
.agent-card {
  position: relative;
  overflow: hidden;
  display: block;
  border-radius: 22px;
  padding: 19px 21px 17px;
  background: linear-gradient(180deg, #161616 0%, #0f0f0f 100%);
  box-shadow: inset 0 0 0 1px var(--rule), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  color: inherit;
  text-decoration: none;
  animation: pop 600ms var(--spring) backwards;
  transition: transform 520ms var(--snappy), box-shadow 300ms var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}
.agent-card::before {
  content: "";
  position: absolute;
  inset-inline: 12%;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(215, 255, 63, 0.35), transparent);
  opacity: 0.55;
  transition: opacity 300ms var(--ease-out);
}
.agent-card:hover {
  transform: translateY(-2px);
  box-shadow: inset 0 0 0 1px var(--rule-strong), inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 22px 46px -30px rgba(0, 0, 0, 0.9);
}
.agent-card:hover::before { opacity: 1; }
.agent-card:active { transform: scale(0.972); transition: transform 130ms ease-out; }
.agent-card.is-stopped { background: linear-gradient(180deg, #131313 0%, #0d0d0d 100%); }

.card-top { display: flex; align-items: center; gap: 10px; }
.card-handle {
  color: var(--ink);
  font-size: 16.5px;
  font-weight: 600;
  letter-spacing: -0.018em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pill {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 25px;
  padding-inline: 11px;
  border-radius: 999px;
  font-size: 12.5px;
  background: rgba(255, 255, 255, 0.06);
  box-shadow: inset 0 0 0 1px var(--rule);
  color: var(--body);
}
.pill .dot { margin: 0; width: 6px; height: 6px; vertical-align: 0; }
.pill.is-active { color: var(--ink); }
.pill.is-active .dot { animation: breathe 3.4s ease-in-out infinite; }
.pill.is-suspended { color: var(--refuse); box-shadow: inset 0 0 0 1px rgba(226, 112, 92, 0.35); }

.card-balance {
  display: flex;
  margin-top: 15px;
  color: var(--ink);
  font-size: 31px;
  font-weight: 600;
  letter-spacing: -0.032em;
}
.card-balance .money-frac { font-size: 0.56em; }
.is-stopped .card-balance .money-int { color: var(--muted); }
.card-balk { display: block; margin-top: 1px; color: var(--muted); font-size: 13px; }

.card-spend {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  margin-top: 15px;
  padding-top: 13px;
  border-top: 1px solid var(--rule);
}
.card-spend .k { display: block; color: var(--muted); font-size: 12.5px; margin-bottom: 1px; }
.card-spend .v { color: var(--body); font-size: 15px; }
.card-spend .right { margin-left: auto; text-align: right; }
.spark { display: block; margin-left: auto; }
.spark-line { fill: none; stroke: var(--muted); stroke-width: 1.25; stroke-linejoin: round; }
.spark-fill { fill: rgba(255, 255, 255, 0.05); stroke: none; }

.card-meters {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 13px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}
.meter .k { color: var(--muted); font-size: 12.5px; }
.meter .v { float: right; color: var(--body); font-size: 15px; font-variant-numeric: tabular-nums; }
.meter .track {
  clear: both;
  height: 3px;
  border-radius: 2px;
  margin-top: 7px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}
.meter .fill {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: var(--signal);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 800ms var(--ease-out);
}
/* correctness is the sparse dimension: it never borrows the dense one's colour */
.meter.is-sparse .fill { background: var(--body); }
.meter .n { display: block; margin-top: 5px; color: var(--muted); font-size: 12px; }

.empty { padding: 30px 0 0; }
.empty-what { color: var(--ink); font-size: 19px; margin-bottom: 18px; }
.empty-why { color: var(--muted); font-size: 14.5px; max-width: 52ch; }

/* =======================================================================
 * The agent screen (M9): a rail that stays, and a tabbed working area.
 *
 * EVERYTHING INSIDE A TAB IS EXPRESSED IN THE TOKENS BELOW. A panel, a
 * settings group, one line of that group, a field and a data table each read
 * their surface, corner, spacing and rule from a `--panel-*`, `--group-*`,
 * `--line-*`, `--field-*` or `--cell-*` variable, and none of the three tabs
 * carries a style of its own. Re-colouring or re-spacing the tabs is therefore
 * a change to this token block, not a change to the three panels.
 * ======================================================================= */

:root {
  /* the panel: one tab's surface */
  --panel-radius: 22px;
  --panel-pad: clamp(18px, 2vw, 24px);
  --panel-bg: linear-gradient(180deg, #161616 0%, #0f0f0f 100%);
  --panel-ring: inset 0 0 0 1px var(--rule), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  --panel-gap: 16px;

  /* a grouped list inside a panel */
  --group-radius: 16px;
  --group-bg: rgba(255, 255, 255, 0.03);
  --group-ring: inset 0 0 0 1px var(--rule);

  /* one line of that group */
  --line-pad-y: 14px;
  --line-pad-x: 16px;
  --line-gap: 16px;
  --line-rule: var(--rule);
  --line-hover: rgba(255, 255, 255, 0.03);
  --line-label-size: 15px;
  --line-label-ink: var(--ink);
  --line-note-size: 12.5px;
  --line-note-ink: var(--muted);

  /* a field a person types into */
  --field-bg: rgba(255, 255, 255, 0.05);
  --field-radius: 10px;
  --field-pad: 8px 11px;
  --field-width: 12ch;
  --field-ring: inset 0 0 0 1px var(--rule);
  --field-ring-hover: inset 0 0 0 1px var(--rule-strong);
  --field-ring-focus: inset 0 0 0 1px var(--signal);

  /* a row of a data table inside a panel */
  --cell-pad-y: 9px;
  --cell-pad-x: 20px;
  --cell-size: 14.5px;
  --cell-rule: rgba(255, 255, 255, 0.055);

  /* how a tab arrives */
  --tab-shift: 18px;
  --tab-in: 460ms;
  --row-stagger: 30ms;
}

.back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 18px;
  color: var(--muted);
  font-size: 14.5px;
  text-decoration: none;
}
.back:hover { color: var(--ink); }
.back-arrow { transition: transform 420ms var(--snappy); }
.back:hover .back-arrow { transform: translateX(-4px); }

.split { display: grid; gap: 20px; align-items: start; }
.split > * { min-width: 0; }
@media (min-width: 940px) { .split { grid-template-columns: 340px minmax(0, 1fr); } }

/* ---------- the rail ---------- */
.rail {
  position: sticky;
  top: 84px;
  overflow: hidden;
  border-radius: var(--panel-radius);
  padding: var(--panel-pad);
  background: var(--panel-bg);
  box-shadow: var(--panel-ring);
  animation: pop 600ms var(--spring) backwards;
}
.rail::before {
  content: "";
  position: absolute;
  inset-inline: 12%;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(215, 255, 63, 0.35), transparent);
}
@media (max-width: 939px) { .rail { position: static; } }

.rail h1 {
  font-size: 22px;
  letter-spacing: -0.024em;
  line-height: 1.2;
  margin: 0 0 10px;
  overflow-wrap: anywhere;
}
.rail-balance { display: flex; margin-top: 16px; color: var(--ink); font-size: 34px;
  font-weight: 600; letter-spacing: -0.032em; }
.rail-balance .money-frac { font-size: 0.56em; }
.rail-k { margin-top: 2px; color: var(--muted); font-size: 13px; }

.rail .meters, .rail dl, .rail-danger {
  margin-top: 16px;
  padding-top: 15px;
  border-top: 1px solid var(--rule);
}
.rail dl { display: grid; grid-template-columns: 1fr; gap: 10px; }
.rail dt { color: var(--muted); font-size: 12.5px; }
.rail dd {
  margin: 0;
  color: var(--body);
  font-size: 13px;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;
  overflow-wrap: anywhere;
  word-break: break-all;
}
.rail-danger { border-top-color: rgba(226, 112, 92, 0.3); }
.rail-danger p { color: var(--muted); font-size: 13px; margin-bottom: 12px; }

/* ---------- the tabs ---------- */
.tabs {
  display: flex;
  gap: 4px;
  width: max-content;
  max-width: 100%;
  padding: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  box-shadow: inset 0 0 0 1px var(--rule);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs button {
  height: 34px;
  padding-inline: 18px;
  border-radius: 999px;
  background: transparent;
  box-shadow: none;
  color: var(--muted);
  font-size: 14.5px;
}
.tabs button:hover { background: rgba(255, 255, 255, 0.06); box-shadow: none; }
.tabs button.is-on { background: rgba(255, 255, 255, 0.1); color: var(--ink); }

/* ---------- a panel ---------- */
.panel {
  margin-top: var(--panel-gap);
  border-radius: var(--panel-radius);
  padding: var(--panel-pad);
  background: var(--panel-bg);
  box-shadow: var(--panel-ring);
  animation: tabin var(--tab-in) var(--spring) backwards;
}
.panel-lead { color: var(--muted); font-size: 14px; max-width: 64ch; margin-bottom: 14px; }
.panel-foot { display: flex; align-items: center; gap: 14px; margin-top: 16px; flex-wrap: wrap; }
.panel-foot #policy-status { color: var(--muted); font-size: 14px; }

/* ---------- a grouped list, and one line of it ---------- */
.group {
  border-radius: var(--group-radius);
  overflow: hidden;
  background: var(--group-bg);
  box-shadow: var(--group-ring);
}
.group .line {
  display: flex;
  /* `label` is a column flex elsewhere on the dashboard; a line is a row. */
  flex-direction: row;
  align-items: center;
  gap: var(--line-gap);
  padding: var(--line-pad-y) var(--line-pad-x);
  border-bottom: 1px solid var(--line-rule);
  color: var(--line-label-ink);
  font-size: var(--line-label-size);
  transition: background 200ms var(--ease-out);
}
.group .line:last-child { border-bottom: 0; }
.group .line:hover { background: var(--line-hover); }
.line-note { margin-left: auto; color: var(--line-note-ink); font-size: var(--line-note-size);
  text-align: right; }
.line-sub { display: block; color: var(--line-note-ink); font-size: var(--line-note-size);
  margin-top: 2px; }
.line input[type="text"] {
  flex: none;
  margin-left: auto;
  width: var(--field-width);
  padding: var(--field-pad);
  border: 0;
  border-radius: var(--field-radius);
  background: var(--field-bg);
  box-shadow: var(--field-ring);
  color: var(--ink);
  font-size: 15px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  transition: box-shadow 200ms var(--ease-out);
}
.line input[type="text"]:hover { box-shadow: var(--field-ring-hover); }
.line input[type="text"]:focus { outline: none; box-shadow: var(--field-ring-focus); }
.line .switch { margin-left: auto; }

/* an iOS switch. A <label> is inline by default, so the track needs a box. */
.switch { position: relative; display: inline-block; width: 46px; height: 28px; flex: none; }
.switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  z-index: 1;
  cursor: pointer;
}
.switch .track {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.22);
  box-shadow: inset 0 0 0 1px var(--rule-strong);
  transition: background 260ms var(--ease-out);
}
.switch .track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  transition: transform 460ms var(--snappy);
}
.switch input:checked + .track { background: var(--signal); }
.switch input:checked + .track::after { transform: translateX(18px); }
.switch input:focus-visible + .track { box-shadow: inset 0 0 0 2px var(--signal); }

/* ---------- a data table inside a panel ---------- */
.data-table th, .data-table td {
  padding: var(--cell-pad-y) var(--cell-pad-x) var(--cell-pad-y) 0;
  border-bottom: 1px solid var(--cell-rule);
  font-size: var(--cell-size);
}
/* A ledger account is long enough to push the amount off the panel. The cell
   is CLIPPED, not shortened: the whole value is still in the page, and the
   Ledger screen shows every column at full width. */
.data-table td { max-width: 22ch; overflow: hidden; text-overflow: ellipsis; }
.data-table tr:hover td { background: var(--line-hover); }
.data-table td .money { color: var(--ink); }
.data-table tr[data-row] { animation: rise 420ms var(--spring) backwards; }

/* the suspension notice: the one place coral is a background */
.notice-box {
  border-radius: 18px;
  padding: 16px 18px;
  margin-bottom: 16px;
  background: rgba(226, 112, 92, 0.07);
  box-shadow: inset 0 0 0 1px rgba(226, 112, 92, 0.35);
  animation: rise 520ms var(--spring) backwards;
}
.notice-box p { color: var(--refuse); margin-bottom: 12px; max-width: 70ch; }
#agent-unsuspend-status { color: var(--muted); font-size: 14px; }
#agent-unsuspend-status:empty { display: none; }

/* =======================================================================
 * The ledger screen (M9) — "the console"
 *
 * Built for scanning thousands of entries rather than eighteen: one line each,
 * the kind as a small tag, one right-aligned money column, and a line that
 * opens in place for the two accounts in full, the entry number and the
 * reference. The filters are pills that open a small sheet each.
 * ======================================================================= */

.head { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; margin-bottom: 18px; }
.head h1 { margin: 0; }
.count { color: var(--muted); font-size: 14.5px; font-variant-numeric: tabular-nums; }
.count b { color: var(--ink); font-weight: 600; }

/* ---------- the filter pills ---------- */
.pills { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.pill-control { position: relative; }
.pill-button {
  height: 38px;
  padding-inline: 16px;
  gap: 9px;
  background: rgba(255, 255, 255, 0.05);
  box-shadow: inset 0 0 0 1px var(--rule);
  color: var(--body);
  font-size: 14.5px;
  font-weight: 400;
}
.pill-button .k { color: var(--muted); }
.pill-button .v { color: var(--ink); }
.pill-button .caret { color: var(--muted); font-size: 11px; }
.pill-button.is-set { box-shadow: inset 0 0 0 1px rgba(215, 255, 63, 0.5); }
.pills .grow { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* A sheet: small, over the list, and near the pill that opened it. */
.sheet {
  position: absolute;
  top: 46px;
  left: 0;
  z-index: 30;
  min-width: 232px;
  max-height: min(58vh, 420px);
  overflow-y: auto;
  border-radius: 18px;
  padding: 12px;
  background: linear-gradient(180deg, #1a1a1a 0%, var(--raised) 100%);
  box-shadow: inset 0 0 0 1px var(--rule-strong), 0 26px 60px -30px #000;
  animation: sheetin 320ms var(--spring) backwards;
}
.sheet.is-wide { min-width: 268px; }
@keyframes sheetin {
  from { opacity: 0; transform: translateY(-8px) scale(0.97); }
  to { opacity: 1; transform: none; }
}
/* The select each sheet holds IS that filter's value. It is not shown, because
   a native menu opening inside an open sheet is a second popup over the first;
   the list of choices below it is how a person sets it. */
.sheet .held { display: none; }
.sheet label { display: block; margin-bottom: 6px; font-size: 13px; }
.sheet input {
  display: block;
  width: 100%;
  margin-bottom: 12px;
  font-size: 16px;
  padding: 8px 11px;
  border-radius: 10px;
  border: 0;
  box-shadow: inset 0 0 0 1px var(--rule);
  background: rgba(255, 255, 255, 0.06);
}
.sheet input:last-of-type { margin-bottom: 8px; }
.sheet .utc { color: var(--muted); font-size: 12.5px; margin: 0; }
.sheet .options { display: grid; gap: 2px; }
.sheet .options button {
  justify-content: flex-start;
  height: 34px;
  padding-inline: 11px;
  border-radius: 10px;
  background: transparent;
  box-shadow: none;
  color: var(--body);
  font-size: 14.5px;
  font-weight: 400;
}
.sheet .options button:hover { background: rgba(255, 255, 255, 0.07); box-shadow: none; }
.sheet .options button.on { background: rgba(255, 255, 255, 0.11); color: var(--ink); }

/* ---------- the cap, on the line under the filters ---------- */
.capped {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 14px 0 0;
  color: var(--body);
  font-size: 13.5px;
}
.capped:empty { display: none; }
.capped::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--signal);
}

/* ---------- the blotter ---------- */
.blotter { margin-top: 18px; border-top: 1px solid var(--rule); }

.line {
  display: grid;
  grid-template-columns: 132px 124px minmax(0, 1fr) 160px 22px;
  gap: 4px 16px;
  align-items: center;
  width: 100%;
  min-height: 58px;
  height: auto;
  padding: 10px 2px;
  text-align: left;
  border-radius: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.055);
  background: transparent;
  box-shadow: none;
  color: inherit;
  font-weight: 400;
  animation: linein 400ms var(--spring) backwards;
  transition: background 260ms var(--ease-out), opacity 260ms var(--ease-out),
    box-shadow 260ms var(--ease-out);
}
@keyframes linein { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
.line:hover { background: rgba(255, 255, 255, 0.035); box-shadow: none; }
.line:active { transform: none; }
.line:focus-visible { outline-offset: -2px; }

.line .at {
  color: var(--muted);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.tag {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding-inline: 9px;
  border-radius: 7px;
  font-size: 12px;
  letter-spacing: -0.005em;
  background: rgba(255, 255, 255, 0.07);
  color: var(--body);
}
.tag.k-mint, .tag.k-escrow_release { color: var(--signal); background: rgba(215, 255, 63, 0.12); }
.tag.k-fee, .tag.k-escrow_refund { color: var(--refuse); background: rgba(226, 112, 92, 0.12); }

.line .who {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  color: var(--body);
  font-size: 13.5px;
}
.line .who em {
  font-style: normal;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.line .who .arrow { flex: none; color: var(--muted); }
.line .amount {
  justify-self: end;
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
}
.line.is-in .amount::before { content: "+"; color: var(--signal); margin-right: 2px; }
.line.is-out .amount::before { content: "\2212"; color: var(--muted); margin-right: 2px; }
.line.is-out .amount { color: var(--body); }
.line .chev {
  justify-self: end;
  color: var(--muted);
  font-size: 12px;
  transition: transform 420ms var(--spring), color 260ms var(--ease-out);
}
.line.is-open .chev { transform: rotate(90deg); color: var(--ink); }

/* While one line is open the rest of the list steps back, so attention is on
   the one thing that was asked for. */
.blotter.has-open .line:not(.is-open),
.jobs-list.has-open .job:not(.is-open),
.keyring.has-open .keycard:not(.is-asking) { opacity: 0.55; }
.blotter.has-open .line:not(.is-open):hover,
.jobs-list.has-open .job:not(.is-open):hover { opacity: 0.85; }

/* An open line is tinted by what the entry IS: lime for money arriving, a
   neutral tone for money leaving, coral for the two kinds that are a cost you
   did not choose. The tint is a wash and an edge, never the text's colour. */
.line.is-open {
  background: rgba(255, 255, 255, 0.045);
  box-shadow: inset 2px 0 0 0 var(--rule-strong);
}
.line.is-open.tint-in {
  background: rgba(215, 255, 63, 0.055);
  box-shadow: inset 2px 0 0 0 var(--signal);
}
.line.is-open.tint-refuse {
  background: rgba(226, 112, 92, 0.06);
  box-shadow: inset 2px 0 0 0 var(--refuse);
}

/* The panel: a spring on the way open, over a gradient that fades out of the
   tint. `grid-template-rows` carries the height, so nothing is clipped however
   long a reference is; a browser that will not interpolate it simply arrives at
   the same place without the ease, and with animation off the static rule below
   is what shows. */
.detail {
  display: grid;
  grid-template-rows: 1fr;
  border-bottom: 1px solid rgba(255, 255, 255, 0.055);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0));
  animation: openin 420ms var(--spring) backwards;
}
.detail.tint-in {
  background: linear-gradient(180deg, rgba(215, 255, 63, 0.07), rgba(215, 255, 63, 0));
}
.detail.tint-refuse {
  background: linear-gradient(180deg, rgba(226, 112, 92, 0.07), rgba(226, 112, 92, 0));
}
@keyframes openin {
  from { grid-template-rows: 0fr; opacity: 0; }
  to { grid-template-rows: 1fr; opacity: 1; }
}
.detail-in { overflow: hidden; min-height: 0; }
.detail dl {
  grid-template-columns: 124px minmax(0, 1fr);
  gap: 8px 20px;
  padding: 16px 2px 18px;
  margin: 0;
}
.detail dt { font-size: 12.5px; }
.detail dd {
  color: var(--body);
  font-size: 13px;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  overflow-wrap: anywhere;
}

/* =======================================================================
 * The jobs screen (M9) — "the flight deck"
 *
 * What is still running sits in a lit panel above the heaviest line on the
 * screen, each job carrying the time left and a bar across its own window;
 * what is finished sits below it, grouped by day. A row opens exactly as a
 * ledger line does — the same spring, the same panel, the same stepping back —
 * because it is the same dashboard.
 * ======================================================================= */

.hint-tight { margin-top: 0; margin-bottom: 22px; }

/* ---------- the live panel ---------- */
.flight {
  border-radius: 20px;
  padding: 18px 20px 6px;
  background: linear-gradient(180deg, rgba(215, 255, 63, 0.05), rgba(215, 255, 63, 0));
  box-shadow: inset 0 0 0 1px rgba(215, 255, 63, 0.22);
}
.flight-head { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.flight-head h2 {
  display: flex; align-items: baseline; gap: 9px;
  margin: 0; color: var(--ink); font-size: 18px; font-weight: 600; letter-spacing: -0.02em;
}
.flight-head .dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--signal);
  animation: breathe 2.6s var(--ease-out) infinite;
}
.flight-head .k, .head2 .k { color: var(--muted); font-size: 13.5px; }
.flight-head .clock {
  margin-left: auto;
  color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums;
  padding: 5px 11px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.05); box-shadow: inset 0 0 0 1px var(--rule);
}
.flight-lead {
  margin: 10px 0 4px; max-width: 86ch;
  color: var(--muted); font-size: 13px; line-height: 1.55;
}

/* ---------- the line between running and finished ---------- */
.below {
  display: flex; align-items: center; gap: 16px;
  margin: 30px 0 4px;
  color: var(--muted); font-size: 13px;
}
.below::before { content: ""; width: 26px; height: 1px; background: var(--rule-strong); }
.below::after { content: ""; flex: 1; height: 1px; background: var(--rule-strong); }

.head2 { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; margin: 26px 0 4px; }
.head2 h2 { margin: 0; color: var(--ink); font-size: 18px; font-weight: 600;
  letter-spacing: -0.02em; }
.head2 .k { margin-left: auto; }

/* ---------- a job ---------- */
.jobs-list { border-top: 1px solid var(--rule); margin-top: 12px; }
.flight .jobs-list { border-top-color: rgba(215, 255, 63, 0.18); }

.jday {
  padding: 16px 2px 7px;
  color: var(--muted); font-size: 12.5px; letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid rgba(255, 255, 255, 0.055);
}

.job {
  display: grid;
  grid-template-columns: 116px 86px minmax(0, 92px) 62px 104px 92px minmax(120px, 1fr) 112px 128px 20px;
  gap: 4px 14px;
  align-items: center;
  width: 100%;
  /* The capsule rule gives every button a fixed 38px height. A job is a row,
     not a capsule, and on a phone it folds onto four lines — so the height is
     handed back to the content, exactly as a ledger line does it. Without this
     the box stays 38px while its rows lay out below it and the list overlaps. */
  height: auto;
  min-height: 62px;
  padding: 11px 2px;
  text-align: left;
  border: 0; border-radius: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.055);
  background: transparent;
  box-shadow: none;
  color: inherit;
  font-weight: 400;
  animation: linein 400ms var(--spring) backwards;
  transition: background 260ms var(--ease-out), opacity 260ms var(--ease-out),
    box-shadow 260ms var(--ease-out);
}
.job:hover { background: rgba(255, 255, 255, 0.035); box-shadow: none; }
.job:active { transform: none; }
.job:focus-visible { outline-offset: -2px; }
/* While a row is travelling it is above the rows it passes, and nothing it is
   doing may be interrupted by a hover. */
.job.is-moving { position: relative; z-index: 3; pointer-events: none; }

.job .at { color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.job .jid {
  color: var(--ink); font-size: 13px;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
}
.job .jtype, .job .jwho { color: var(--body); font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.job .jwho { font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px; }

.jrole {
  display: inline-flex; align-items: center; height: 21px; padding-inline: 8px;
  border-radius: 6px; font-size: 11.5px; letter-spacing: 0.01em;
  background: rgba(255, 255, 255, 0.06); color: var(--muted);
}
.jrole.r-buyer { color: var(--body); }

/* The state pill morphs where it stands rather than being replaced. */
.jpill {
  display: inline-flex; align-items: center; gap: 7px; height: 24px; padding-inline: 10px;
  border-radius: 7px; font-size: 12px;
  background: rgba(255, 255, 255, 0.07); color: var(--body);
  transition: background 420ms var(--ease-out), color 420ms var(--ease-out),
    box-shadow 420ms var(--ease-out);
}
.jpill .dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.jpill.is-morphing { animation: morph 560ms var(--snappy); }
@keyframes morph {
  0% { transform: scale(1); }
  38% { transform: scale(1.09); }
  100% { transform: scale(1); }
}
.st-job-open { background: var(--signal); }
.st-job-accepted, .st-job-delivered, .st-job-verifying { background: rgba(255, 255, 255, 0.5); }
.st-job-settled { background: var(--signal); }
.st-job-refunded, .st-job-rejected { background: var(--refuse); }
.st-job-expired, .st-job-cancelled { background: rgba(255, 255, 255, 0.28); }
.jpill.s-open { color: var(--signal); background: rgba(215, 255, 63, 0.12); }
.jpill.s-settled { color: var(--ink); background: rgba(215, 255, 63, 0.1); }
.jpill.s-refunded, .jpill.s-rejected { color: var(--refuse); background: rgba(226, 112, 92, 0.12); }

/* The clock: the words above, the bar under them, both computed on the page. */
.jclock { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.job .jleft { color: var(--body); font-size: 12.5px; font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.job .jleft.is-over { color: var(--refuse); }
.jbar { display: block; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, 0.09); }
.jbar .fill {
  display: block; height: 100%; width: 0; border-radius: 2px;
  /* `--near` is set by the page, 0 to 1, as the deadline comes up. The mix is
     done HERE so lime and amber are declared once; a browser that cannot mix
     keeps the lime it is given on the line above. */
  --near: 0;
  background: var(--signal);
  background: color-mix(in oklab, var(--signal), var(--warn) calc(var(--near) * 100%));
  /* Painted a few times a second; the transition carries it the rest of the
     way, so the bar fills continuously rather than stepping. */
  transition: width 260ms linear, background 600ms linear;
}
.jbar .fill.is-over { background: var(--refuse); }
/* A finished job has no clock to show: its window closed. */
.job:not(.is-live) .jclock { visibility: hidden; }
.job:not(.is-live) .jdeadline { color: var(--muted); font-size: 12.5px; }

.job .jprice { justify-self: end; color: var(--ink); font-size: 14.5px; font-weight: 600; }
.job .jout { font-size: 12.5px; text-align: right; }
.jout.is-passed { color: var(--signal); }
.jout.is-refused { color: var(--refuse); }
.jout.is-none { color: var(--muted); }
/* Not a gap: a seller is told the state and nothing more, and the row says so
   in the dashboard's own words rather than leaving a hole where a buyer has
   an outcome. */
.jout.is-untold {
  color: var(--muted); font-size: 11.5px;
  padding: 3px 8px; border-radius: 6px;
  box-shadow: inset 0 0 0 1px var(--rule);
}
.job .chev {
  justify-self: end; color: var(--muted); font-size: 12px;
  transition: transform 420ms var(--spring), color 260ms var(--ease-out);
}
.job.is-open .chev { transform: rotate(90deg); color: var(--ink); }
.job.is-open { background: rgba(255, 255, 255, 0.045);
  box-shadow: inset 2px 0 0 0 var(--rule-strong); }

/* =======================================================================
 * API keys (M9) — "the keyring"
 *
 * One column, one card per key, and EVERY card on the same four-track grid —
 * the create card included — so names, dates and agent lists line up straight
 * down the list and it reads as a column rather than as a heap of boxes. A key
 * holding agents up is the heavy thing on the page; a key holding none is
 * quiet, so the safe one to revoke is obvious before anything is clicked. The
 * two dangerous acts open the ledger's panel, on the ledger's spring.
 * ======================================================================= */

.keys-head { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; margin-bottom: 8px; }
.keys-head h2 { margin: 0; }
.keys-head .count { color: var(--muted); font-size: 13.5px; }
.keys-head #close-keys { margin-left: auto; }
.keys-lead { color: var(--body); max-width: 78ch; margin-bottom: 12px; }
.keys-warn {
  border-radius: 14px;
  padding: 13px 16px;
  margin-bottom: 20px;
  max-width: 88ch;
  color: var(--body);
  font-size: 14.5px;
  background: rgba(226, 112, 92, 0.05);
  box-shadow: inset 0 0 0 1px rgba(226, 112, 92, 0.3);
}
.keys-warn strong { color: var(--ink); }

/* ---------- the once-only secret ---------- */
.once-kicker {
  color: var(--signal); font-size: 11.5px; letter-spacing: 0.09em; text-transform: uppercase;
  margin-bottom: 8px;
}
.once-acts { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.once-report {
  margin: 0 0 12px; padding-top: 12px;
  border-top: 1px solid rgba(226, 112, 92, 0.3);
  color: var(--refuse); font-size: 14px; max-width: 76ch;
}
.once-report:empty { display: none; }

/* ---------- the ring ---------- */
.keyring { display: grid; gap: 10px; }

.keycard {
  display: grid;
  /* the one grid every card shares */
  grid-template-columns: minmax(0, 1.15fr) 190px minmax(0, 1.5fr) auto;
  gap: 4px 24px;
  align-items: start;
  height: auto;
  padding: 16px 18px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.022);
  box-shadow: inset 0 0 0 1px var(--rule);
  transition: background 260ms var(--ease-out), box-shadow 260ms var(--ease-out),
    opacity 260ms var(--ease-out);
  animation: rise 420ms var(--spring) backwards;
}
/* A key with agents on it is heavier: a lit edge, a brighter ground. */
.keycard.is-carrying {
  background: rgba(215, 255, 63, 0.04);
  box-shadow: inset 0 0 0 1px rgba(215, 255, 63, 0.26), inset 3px 0 0 0 var(--signal);
}
.keycard.is-idle { background: rgba(255, 255, 255, 0.015); }
.keycard.is-dead { background: transparent; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06); }
.keycard.is-dead .kc-name span:first-child, .keycard.is-dead .kc-when .v { color: var(--muted); }
.keycard.is-asking { box-shadow: inset 0 0 0 1px var(--rule-strong), inset 3px 0 0 0 var(--refuse); }

.kc-main { min-width: 0; }
.kc-name {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 0 0 4px;
  color: var(--ink); font-size: 16px; font-weight: 600; letter-spacing: -0.016em;
}
.kpill {
  display: inline-flex; align-items: center; height: 20px; padding-inline: 8px;
  border-radius: 6px; font-size: 11.5px; font-weight: 500; letter-spacing: 0;
}
.kpill.is-live { color: var(--signal); background: rgba(215, 255, 63, 0.12); }
.kpill.is-revoked { color: var(--muted); background: rgba(255, 255, 255, 0.06); }
.kc-sub { margin: 0; color: var(--muted); font-size: 12.5px; }
.kc-id { font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px; overflow-wrap: anywhere; }

.kc-when { display: grid; gap: 3px; align-content: start; }
.kc-when .k { color: var(--muted); font-size: 11.5px; letter-spacing: 0.04em;
  text-transform: uppercase; }
.kc-when .v { color: var(--body); font-size: 13px; font-variant-numeric: tabular-nums; }
.kc-age { color: var(--muted); font-size: 12px; }
.kc-when label { color: var(--muted); font-size: 11.5px; letter-spacing: 0.04em;
  text-transform: uppercase; margin-bottom: 3px; }
.kc-when input { width: 100%; font-size: 16px; padding: 8px 11px; }

.kc-carrying { min-width: 0; }
.kc-lead { margin: 0 0 8px; color: var(--body); font-size: 13px; }
.kc-none { margin: 0; color: var(--muted); font-size: 13px; }
.kagents { display: flex; flex-wrap: wrap; gap: 6px; }
.kagent {
  display: inline-flex; align-items: center; gap: 7px;
  height: 24px; padding-inline: 9px; border-radius: 7px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--ink); font-size: 12.5px;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
}
.kagent .dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.kagent .kstat { font-style: normal; color: var(--refuse); font-size: 11px;
  font-family: var(--font); }

.kc-acts { display: flex; gap: 8px; align-items: start; justify-self: end; }
.kc-acts button { height: 34px; font-size: 14px; }

/* the create card: the same grid, louder when it is the only thing here */
.keycard.is-new { box-shadow: inset 0 0 0 1px var(--rule-strong); }
.keycard.is-new.is-first {
  background: rgba(215, 255, 63, 0.05);
  box-shadow: inset 0 0 0 1px rgba(215, 255, 63, 0.4);
  padding-block: 22px;
}
.keycard.is-new .kc-name { color: var(--ink); }

/* ---------- asking first ---------- */
.kask { border-radius: 0 0 16px 16px; margin-top: -8px; }
.kask .detail-in { padding-inline: 18px; }
.kask-kicker {
  margin: 14px 0 6px;
  color: var(--refuse); font-size: 11.5px; letter-spacing: 0.09em; text-transform: uppercase;
}
.kask-says { margin: 0 0 14px; color: var(--ink); font-size: 14.5px; max-width: 82ch; }
.kask-agents { display: grid; gap: 6px; margin-bottom: 14px; }
.kask-agent { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.kask-id { color: var(--muted); font-size: 11.5px;
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace; }
.kask-agent a { color: var(--body); font-size: 12.5px; }
.kask-ack {
  /* The shared `label` rule stacks its parts in a column, which would put the
     box on its own line above the sentence it is agreeing to. */
  display: flex; flex-direction: row; align-items: flex-start; gap: 10px;
  margin-bottom: 16px; max-width: 82ch;
  color: var(--body); font-size: 14px; line-height: 1.5;
}
.kask-ack input { margin-top: 2px; flex: none; }
.kask-safe { margin: 0 0 16px; color: var(--muted); font-size: 14px; }
.kask-foot { display: flex; gap: 10px; align-items: center; padding-bottom: 18px; }

/* =======================================================================
 * Making an agent, funding it, and what was refused (M10)
 * ======================================================================= */

/* The first card on the agents screen, on the keyring's grid so the two
   creation surfaces in the product read the same way. */
.newagent {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) 260px auto;
  gap: 6px 24px;
  align-items: start;
  height: auto;
  padding: 18px 20px;
  margin-bottom: 18px;
  border-radius: 16px;
  background: rgba(215, 255, 63, 0.05);
  box-shadow: inset 0 0 0 1px rgba(215, 255, 63, 0.35);
}
.na-title { margin: 0 0 4px; color: var(--ink); font-size: 16px; font-weight: 600;
  letter-spacing: -0.016em; }
.na-sub { margin: 0; color: var(--muted); font-size: 12.5px; max-width: 62ch; }
.na-field label { color: var(--muted); font-size: 11.5px; letter-spacing: 0.04em;
  text-transform: uppercase; margin-bottom: 4px; display: block; }
.na-field input { width: 100%; }
.na-acts { justify-self: end; align-self: end; }
.na-cannot {
  grid-column: 1 / -1;
  margin: 10px 0 0; padding: 12px 14px; border-radius: 12px;
  color: var(--body); font-size: 14px; max-width: 80ch;
  background: rgba(226, 112, 92, 0.06);
  box-shadow: inset 0 0 0 1px rgba(226, 112, 92, 0.35);
}
.once-what { color: var(--muted); font-size: 13px; margin-bottom: 10px; max-width: 74ch; }

/* Funding, on the rail beside the balance it changes. */
.rail-fund { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--rule); }
.rail-fund label { color: var(--muted); font-size: 11.5px; letter-spacing: 0.04em;
  text-transform: uppercase; display: block; margin-bottom: 6px; }
.fund-row { display: flex; gap: 8px; }
.fund-row input { flex: 1; min-width: 0; }
.fund-left { color: var(--muted); font-size: 12.5px; margin-top: 8px; }
#fund-status { color: var(--body); font-size: 13px; margin-top: 6px; }
#fund-status:empty { display: none; }

/* What policy refused: the ledger's line, one fact per row. */
.refusals { border-top: 1px solid var(--rule); }
/* The reason takes a line of its own at every width. Squeezed into a fourth
   column beside the other three it had about 120px inside this panel, and the
   one sentence a person opens this tab to read — what was asked, against what
   was allowed — broke across four lines (walked in a real browser,
   2026-09-23). One layout, not two: this is what the phone already did. */
.refusal {
  display: grid;
  grid-template-columns: 132px 104px minmax(0, 1fr);
  gap: 4px 16px;
  align-items: baseline;
  padding: 13px 2px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.055);
  animation: linein 400ms var(--spring) backwards;
}
.refusal .why { grid-column: 1 / -1; }
.refusal .at { color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.refusal .asked { color: var(--body); font-size: 13px; }
.refusal .asked .k { color: var(--muted); }
.refusal .why { color: var(--refuse); font-size: 13px; }
.refusal .why .against { color: var(--muted); }

/* ---------- motion ----------
 * EVERY entrance here fills `backwards`, never `both`, and that is a rule
 * rather than a preference. A forwards fill keeps the animation's last
 * keyframe applied for ever, and an animation sits ABOVE ordinary declarations
 * in the cascade — so an element that arrives at `transform: none` can never
 * afterwards be moved by a rule, and one that arrives at `opacity: 1` can
 * never be dimmed by one. It has happened twice: the ledger's list did not
 * step back for a row that was open, and the agent card's hover lift and press
 * shrink never once fired while the shadow half of the same gesture did.
 * Both were invisible in a green suite, which is why the standing rule is to
 * test the computed effect and never the marker that is supposed to cause it.
 *
 * `backwards` is safe for all four of these because each ends at the element's
 * natural state — opacity 1, transform none — so the rest state is the
 * stylesheet's, which is where it belongs.
 */
@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes pop { from { opacity: 0; transform: translateY(16px) scale(0.965); } to { opacity: 1; transform: none; } }
@keyframes breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@keyframes tabin { from { opacity: 0; transform: translateX(var(--tab-shift)); }
  to { opacity: 1; transform: none; } }

@media (max-width: 720px) {
  /* Two rows: the account above, one scrollable strip of links below. */
  .bar { flex-wrap: wrap; row-gap: 6px; padding-block: 10px; gap: 12px; min-height: 0; }
  /* Documentation and the signed-in links share the second row, and it
     scrolls sideways rather than wrapping to a third. */
  .bar > a:not(.brand) { order: 3; }
  .bar nav {
    order: 4;
    flex: 1 1 auto;
    gap: 18px;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .bar nav::-webkit-scrollbar { display: none; }
  .bar nav a, .bar > a:not(.brand) { white-space: nowrap; }
  #who { display: none; }
  .cards { grid-template-columns: 1fr; }
  /* the three figures pair up rather than making three tall blocks */
  .figures { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
  .fig { padding: 13px 15px 14px; }
  .fig:last-child { grid-column: 1 / -1; }
  .fig .v { font-size: 20px; }
  /* the capsule above already shows the share; the balance is what matters */
  #agents-share th:nth-child(3), #agents-share td:nth-child(3) { display: none; }
  /* the console, on a phone: the line folds to two rows — what happened and
     the amount above, the two accounts under them — and a sheet takes the
     width it is given rather than hanging off the edge. */
  .line {
    grid-template-columns: minmax(0, 1fr) auto 18px;
    min-height: 0;
    padding-block: 12px;
    row-gap: 5px;
  }
  .line .at { grid-column: 1; grid-row: 1; }
  .line .tagcell { grid-column: 1; grid-row: 2; }
  .line .amount { grid-column: 2; grid-row: 1; }
  .line .chev { grid-column: 3; grid-row: 1; align-self: center; }
  .line .who { grid-column: 1 / -1; grid-row: 3; font-size: 13px; }
  /* The account that has a handle is the one worth reading, so the other
     side — usually an escrow account's raw id — absorbs the truncation
     rather than both ends losing their last characters. */
  .line .who em:first-of-type { flex: 1 1 0; }

  /* the flight deck, on a phone: the job folds to three rows — what it is and
     what it cost, then its side and its state, then the clock and the outcome */
  .job {
    grid-template-columns: minmax(0, 1fr) auto auto 18px;
    min-height: 0;
    padding-block: 13px;
    row-gap: 7px;
  }
  .job .at { grid-column: 1; grid-row: 1; }
  .job .jid { grid-column: 2; grid-row: 1; }
  .job .jprice { grid-column: 3; grid-row: 1; }
  .job .chev { grid-column: 4; grid-row: 1; align-self: center; }
  .job .jtype { grid-column: 1; grid-row: 2; }
  .job .jrole { grid-column: 2; grid-row: 2; justify-self: end; }
  .jpill { grid-column: 3 / -1; grid-row: 2; justify-self: end; }
  .job .jwho { grid-column: 1; grid-row: 3; }
  .job .jout { grid-column: 2 / -1; grid-row: 3; justify-self: end; }
  .jclock { grid-column: 1 / -1; grid-row: 4; }
  .job:not(.is-live) .jclock { display: none; }
  .flight { padding-inline: 14px; }
  .flight-head .clock { margin-left: 0; }

  /* the keyring, on a phone: one card is one column, in reading order —
     what it is, when, what it is holding, then what can be done to it */
  .keycard { grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 15px 15px; }
  .newagent { grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 15px; }
  .na-acts { justify-self: stretch; }
  .na-acts button { width: 100%; }
  .refusal { grid-template-columns: minmax(0, 1fr) auto; row-gap: 6px; }
  .kc-acts { justify-self: stretch; }
  .kc-acts button { flex: 1; }
  .keys-head #close-keys { margin-left: 0; }
  .kask .detail-in { padding-inline: 15px; }
  .detail dl { grid-template-columns: 96px minmax(0, 1fr); }
  .pills { gap: 8px; }
  .pills .grow { margin-left: 0; }
  .sheet { min-width: 0; width: min(78vw, 300px); }
  .pill-control:last-of-type .sheet { left: auto; right: 0; }
}

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