.eyebrow {
  color: var(--color-muted);
  font: 700 0.64rem var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* Per-user run price (Users drill-down + roster). A custom (grandfathered)
   price is marked in the warn tone — it's a deliberate deviation, not an
   error; the section's caveat line carries the not-yet-enforced honesty. */
.price-custom {
  color: var(--color-warn);
  white-space: nowrap;
}
.price-override {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
}
.price-override-reading {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--color-ink);
}
.price-override-error {
  color: var(--color-bad);
  font-size: 0.78rem;
}

/* Paying-user marker (Users roster, this plan): a subtle credit-toned dot
   before the username of any account that has bought at least one prepaid
   pack. Deliberately quiet — no loud badge — the tooltip carries the count. */
.paying-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--color-good);
  vertical-align: middle;
}

/* Lever-card form fields (Users drill-down cards): the adjust/suspend
   reason input flexes to the card, everything stays one row. */
.fig.lever .card-actions .ledger-adjust-reason {
  flex: 1 1 60px;
  width: auto;
  min-width: 0;
  padding-inline: 8px;
}
/* One-line truncating sub (the identity card's email). */
.fig .sub .sub-truncate {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Collapsed by-run forensics (Margins): a native disclosure wearing the
   eyebrow as its summary — one click away, no 30-row slab in the page. */
.by-run-details summary.eyebrow {
  cursor: pointer;
  user-select: none;
}
.by-run-details summary.eyebrow::marker {
  color: var(--color-muted);
}
.by-run-details[open] summary.eyebrow {
  margin-bottom: 10px;
}

.button {
  min-height: 48px;
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-2);
  background: var(--color-ink);
  color: var(--color-surface);
  padding: 0 var(--space-5);
  font-weight: 700;
  font-size: var(--text-sm);
  white-space: nowrap;
}

.button:hover {
  background: color-mix(in srgb, var(--color-ink) 84%, var(--color-accent));
}

.button-secondary {
  background: var(--color-surface-raised);
  color: var(--color-ink);
}

.button-secondary:hover {
  background: color-mix(in srgb, var(--color-surface-raised) 88%, var(--color-accent));
}

.button:disabled {
  cursor: not-allowed;
  opacity: 0.62;
}

/* ── Notice: the unified inline-notification component ────────────────────────
   One family, two sizes (field/block) × four tones, used everywhere an inline
   message appears (validation, load failures, out-of-runs). Counterpart to the
   corner toast stack. Each tone sets --tone-color; the shared rules below key
   off it, so adding a tone is one line. Tones match the toast accents. */
.notice {
  font-size: var(--text-sm);
}

/* Field: bare text under the input it annotates (validation). */
.notice--field {
  color: var(--tone-color);
}

/* Block: tinted box that tops/replaces a region; optional trailing action. */
.notice--block {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  border: 1px solid color-mix(in srgb, var(--tone-color) 40%, var(--color-line));
  border-radius: var(--radius-2);
  background: color-mix(in srgb, var(--tone-color) 12%, var(--color-surface));
  color: var(--tone-color);
  padding: var(--space-3);
}

.notice-message {
  flex: 1 1 auto;
  line-height: 1.4;
}

.notice-action {
  flex: 0 0 auto;
  appearance: none;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  border-radius: var(--radius-2);
  padding: var(--space-1) var(--space-3);
  font: 600 var(--text-xs) var(--font-mono);
  cursor: pointer;
  white-space: nowrap;
}

.notice-action:hover {
  background: color-mix(in srgb, var(--tone-color) 16%, transparent);
}

.notice--info {
  --tone-color: var(--color-info);
}
.notice--success {
  --tone-color: var(--color-good);
}
.notice--warning {
  --tone-color: var(--color-warn);
}
.notice--danger {
  --tone-color: var(--color-bad);
}

/* A block notice placed directly in a pane (e.g. the out-of-runs banner above
   the start form): .l-container aligns it to the content column; this adds the
   gap to the content below, which the bare pane otherwise lacks. */
.pane-notice {
  margin-bottom: var(--space-6);
}

.target-panel {
  --gap: var(--space-2);
}

.target-panel h1 {
  margin: var(--space-1) 0 var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--text-2xl);
}

.target-panel p {
  max-width: 650px;
}

.target-form {
  margin-top: var(--space-8);
  --columns: 3;
  --gap: var(--space-4);
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) auto;
  align-items: end;
}

.target-actions {
  display: flex;
  gap: var(--space-2);
  align-items: end;
}

.field {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}

.field span {
  color: var(--color-muted);
  font: 600 var(--text-sm) var(--font-sans);
}

.field input {
  width: 100%;
  min-height: 48px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-surface-raised);
  color: var(--color-ink);
  padding: 0 var(--space-4);
  outline: none;
}

.field input::placeholder {
  color: var(--color-muted);
}

.field input:focus {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}

.run-queue {
  --gap: var(--space-8);
  margin-top: var(--space-8);
}

.run-section {
  --gap: var(--space-3);
}

.run-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  border-bottom: 1px solid var(--color-line);
  padding: 0 var(--space-3) var(--space-2);
  margin-inline: calc(var(--space-3) * -1);
}

.run-section-header h2 {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-lg);
}

.run-section-header span {
  color: var(--color-muted);
  font: 700 var(--text-xs) var(--font-mono);
}

.run-list {
  display: grid;
}

.run-row {
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  border: 0;
  background: transparent;
  color: var(--color-ink);
  cursor: pointer;
  padding: var(--space-2) var(--space-3);
  margin-inline: calc(var(--space-3) * -1);
  text-align: left;
  transition: background 120ms ease;
}

.run-row:hover {
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

.run-row.is-selected {
  background: color-mix(in srgb, var(--color-accent) 16%, var(--color-surface));
}

.run-row.is-selected:hover {
  background: color-mix(in srgb, var(--color-accent) 20%, var(--color-surface));
}

.run-row-main {
  min-width: 0;
  display: grid;
  gap: 2px;
}

/* Inline title row: the run address with the quiet per-row Retry control
   beside it (D-10, pua-polish). The retry reads as a small text action next to
   the title, not a right-hand gutter. min-width:0 lets the address ellipsize. */
.run-title-row {
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.run-address,
.run-meta {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.run-address {
  min-width: 0;
  font-family: var(--font-serif);
  font-size: var(--text-md);
  font-weight: 700;
  line-height: 1.2;
}

.run-meta {
  color: var(--color-muted);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
}

.run-status {
  flex: 0 0 auto;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-canvas);
  padding: var(--space-1) var(--space-2);
  font: 700 var(--text-xs) var(--font-mono);
}

.run-status.is-active {
  color: var(--color-info);
}

.run-status.is-review {
  color: var(--color-warn);
}

.run-status.is-failed {
  color: var(--color-bad);
}

.run-status.is-complete {
  color: var(--color-good);
}

.run-status.is-none {
  color: var(--color-muted);
}

.run-row-aside {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Per-row Retry: a quiet ghost control, lighter in weight than the status pill
   (D-10) — modelled on .nav-tab, not the heavy ink-filled .button. Rendered
   inline beside the run title; flex:0 0 auto so it is never clipped by the
   address ellipsis. */
.run-retry {
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  color: var(--color-ink-soft);
  font: 700 var(--text-xs) var(--font-mono);
  cursor: pointer;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-2);
}

.run-retry:hover {
  color: var(--color-ink);
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

/* Inspector-header retry (D-10): the same quiet ghost control as the queue row,
   given the header control's slightly roomier padding so it aligns with the
   Close button beside it without gaining the heavy bordered .button weight. */
.detail-header-actions .run-retry {
  min-height: 36px;
  padding: 0 var(--space-3);
}

/* Outcome filter chips on the Recent list (QUEUE-01, D-01) — restrained pills
   matching the app's quiet chrome (the .nav-tab weight reference). */
.run-filter-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.run-chip {
  border: 1px solid var(--color-line);
  background: transparent;
  color: var(--color-ink-soft);
  font: 700 var(--text-xs) var(--font-mono);
  cursor: pointer;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-2);
}

.run-chip:hover {
  color: var(--color-ink);
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

.run-chip.is-active {
  color: var(--color-surface);
  background: var(--color-ink);
  border-color: var(--color-ink);
}

/* Count beside the filter label — secondary to the name: lighter weight and
   dialled-back opacity so it reads as muted on both the default and the
   inverted (.is-active) chip without a per-state colour rule. */
.run-chip-count {
  margin-left: var(--space-2);
  font-weight: 500;
  opacity: 0.55;
}

/* Right-aligned "Retry all failed (N)" trigger + its inline confirm prompt at
   the end of the Recent chip row (pua-polish). margin-left:auto pushes the
   group to the far right of the chip row, away from the filter chips. */
.run-retry-all-group {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* "Retry all failed (N)" trigger on the chip row (pua-polish) — quiet ghost
   control, secondary in weight to the status pill, never the heavy .button. */
.run-retry-all {
  border: 0;
  background: transparent;
  color: var(--color-ink-soft);
  font: 700 var(--text-xs) var(--font-mono);
  cursor: pointer;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-2);
}

.run-retry-all:hover {
  color: var(--color-ink);
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
}

/* Inline "Retry N failed runs?" confirm (pua-polish) — one quiet line: a muted
   prompt followed by Yes / No text links, replacing the heavy filled buttons.
   Sits at the far right of the chip row inside .run-retry-all-group. */
.retry-all-confirm {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.retry-all-prompt {
  color: var(--color-muted);
  font: 400 var(--text-xs) var(--font-sans);
}

/* Yes / No confirm actions rendered as plain text links — lighter than the
   .nav-tab reference: no border, no fill, ink-soft, underline only on hover.
   Kept as <button>s for keyboard/a11y; deliberately NOT .button. */
.text-link {
  border: 0;
  background: transparent;
  color: var(--color-ink-soft);
  font: 400 var(--text-xs) var(--font-sans);
  cursor: pointer;
  padding: 0;
}

.text-link:hover {
  color: var(--color-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Row-action modifiers (Phase 23, /admin/users). Danger = Suspend, Accent =
   Reactivate; hover keeps the tone hue, darkening toward ink like .text-link. */
.text-link.is-danger {
  color: var(--color-bad);
}

.text-link.is-danger:hover {
  color: color-mix(in srgb, var(--color-bad) 80%, var(--color-ink));
}

.text-link.is-accent {
  color: var(--color-accent);
}

.text-link.is-accent:hover {
  color: color-mix(in srgb, var(--color-accent) 80%, var(--color-ink));
}

/* Disabled Impersonate (own row / suspended row). No prior .text-link disabled
   rule existed. */
.text-link:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  text-decoration: none;
}

/* Suspend inline confirm — the .retry-all-confirm recipe with a 40px reason
   input inserted, so center-align rather than baseline. */
.suspend-confirm {
  align-items: center;
}

.run-time {
  color: var(--color-muted);
  font-size: var(--text-xs);
  white-space: nowrap;
}

.run-empty {
  color: var(--color-muted);
  font-size: var(--text-sm);
  padding: var(--space-2) 0 var(--space-4);
}

.detail-drawer {
  position: fixed;
  inset: 0 0 0 auto;
  z-index: 40;
  width: calc(var(--detail-drawer-width) + var(--workbench-offset));
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  border-left: 1px solid var(--color-line);
  background: var(--color-surface);
  box-shadow: var(--shadow-drawer);
}

.detail-drawer > * {
  width: var(--detail-drawer-width);
}

.detail-drawer-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  border-bottom: 1px solid var(--color-line);
  padding: var(--space-5);
}

.detail-title-wrap {
  min-width: 0;
}

.detail-title-wrap h2 {
  margin: var(--space-1) 0;
  font-size: var(--text-xl);
}

.detail-subtitle {
  color: var(--color-muted);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.run-reference {
  margin-top: var(--space-2);
  color: color-mix(in srgb, var(--color-muted) 72%, transparent);
  font: 400 var(--text-xs) var(--font-mono);
  overflow-wrap: anywhere;
}

.drawer-close {
  flex: 0 0 auto;
  min-height: 36px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-surface-raised);
  color: var(--color-ink);
  padding: 0 var(--space-3);
  font: 700 var(--text-xs) var(--font-mono);
}

.drawer-close:hover {
  border-color: var(--color-accent);
}

.detail-drawer-body {
  min-height: 0;
  overflow: auto;
  /* Pack sections to the top: the body grid fills the drawer height, so
     without this the rows stretch and spread content apart while a run is
     still filling in. */
  align-content: start;
  --gap: var(--space-5);
  padding: var(--space-5);
}

.detail-section {
  --gap: var(--space-3);
  border-bottom: 1px solid var(--color-line);
  padding-bottom: var(--space-5);
}

.detail-section:last-child {
  border-bottom: 0;
}

/* People — business cards */
.card-stack {
  display: grid;
  gap: var(--space-4);
}

.biz-card {
  min-width: 0;
  display: grid;
  gap: var(--space-3);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-surface-raised);
  padding: var(--space-4);
  box-shadow: var(--shadow-soft);
}

.biz-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  min-width: 0;
}

.biz-name {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--text-lg);
  line-height: 1.2;
}

.biz-principal-tag {
  flex: 0 0 auto;
  color: var(--color-accent);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
}

.biz-home {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--text-sm);
}

.biz-home-label {
  color: var(--color-muted);
}

.biz-home-value {
  overflow-wrap: anywhere;
}

.biz-no-contact {
  color: var(--color-muted);
  font-size: var(--text-sm);
}

.contact-list {
  display: grid;
  gap: var(--space-2);
}

.contact-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
}

.contact-type {
  flex: 0 0 auto;
  width: 64px;
  color: var(--color-muted);
  font-size: var(--text-xs);
  font-weight: 600;
}

.contact-value {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.contact-value a {
  color: var(--color-accent);
}

.verify-badge {
  flex: 0 0 auto;
  border-radius: var(--radius-1);
  padding: 1px var(--space-2);
  font-size: var(--text-xs);
  font-weight: 600;
}

.verify-badge.is-verified {
  background: color-mix(in srgb, var(--color-good) 18%, transparent);
  color: color-mix(in srgb, var(--color-good) 68%, var(--color-ink));
}

.verify-badge.is-unverified {
  background: color-mix(in srgb, var(--color-warn) 20%, transparent);
  color: color-mix(in srgb, var(--color-warn) 68%, var(--color-ink));
}

.source-link {
  flex: 0 0 auto;
  color: var(--color-muted);
  font-size: var(--text-xs);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.source-link:hover {
  color: var(--color-accent);
}

.biz-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.biz-toggle {
  border: 0;
  background: transparent;
  color: var(--color-accent);
  cursor: pointer;
  padding: 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 600;
}

.biz-toggle::before {
  content: "\25B8  ";
  font-size: 0.8em;
}

.biz-toggle.is-open::before {
  content: "\25BE  ";
}

.biz-panel {
  display: grid;
  gap: var(--space-2);
  border-top: 1px solid var(--color-line);
  padding-top: var(--space-3);
}

.panel-group-label {
  color: var(--color-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.panel-group-label:not(:first-child) {
  margin-top: var(--space-2);
}

.role-line {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
}

.role-main {
  flex: 1 1 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-2);
  min-width: 0;
}

.role-title {
  font-size: var(--text-sm);
  overflow-wrap: anywhere;
}

.role-dates {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.note-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.note-text {
  font-size: var(--text-sm);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* Timeline */
.timeline-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.timeline-title {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-lg);
}

.timeline-list {
  display: grid;
  gap: var(--space-4);
}

.timeline-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-3);
}

.timeline-dot {
  width: 9px;
  height: 9px;
  margin-top: 7px;
  border-radius: 50%;
  background: var(--color-line-strong);
}

.timeline-dot.is-ok {
  background: var(--color-good);
}

.timeline-dot.is-candidate {
  background: var(--color-warn);
}

.timeline-dot.is-failed {
  background: var(--color-bad);
}

.timeline-main {
  min-width: 0;
}

.timeline-headline {
  font-weight: 600;
}

.timeline-detail {
  margin-top: 2px;
  color: var(--color-muted);
  font-size: var(--text-sm);
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.timeline-main .source-link {
  display: inline-block;
  margin-top: var(--space-1);
}

/* Admin-only raw failure detail (ERROR-01, D-05). Deliberately quiet/neutral —
   not the alarming full-red banner — since the friendly message already conveys
   the failure; this is the diagnostic dump for an admin to read. */
.detail-error-detail {
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-surface);
  padding: var(--space-3);
}

.detail-error-label {
  color: var(--color-muted);
  font-size: var(--text-xs);
}

.detail-error-raw {
  margin: 0;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--text-sm);
  color: var(--color-muted);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;
  max-height: 12rem;
  overflow: auto;
}

.detail-refreshing,
.empty-inline {
  color: var(--color-muted);
  font-size: var(--text-sm);
}

/* --- Token usage & cost (Phase 12, COST-06) ------------------------------- */

/* Compact per-run USD figure in the queue row aside. */
.run-cost {
  color: var(--color-muted);
  font: 400 var(--text-xs) var(--font-mono);
  white-space: nowrap;
}

/* Token count pill in the inspector's Token Usage & Cost section. */
.token-pill {
  display: grid;
  gap: 2px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-canvas);
  padding: var(--space-2) var(--space-3);
}

.token-pill-label {
  font: 700 var(--text-xs) var(--font-mono);
  color: var(--color-muted);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.token-pill-value {
  font: 400 var(--text-xs) var(--font-mono);
  color: var(--color-ink);
}

/* The "Run cost: $0.0000 [EXACT] (suffix)" line below the pill cluster. */
.run-cost-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.run-cost-line-label {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
}

.run-cost-line-value {
  font: 400 var(--text-sm) var(--font-mono);
  color: var(--color-ink);
}

.run-cost-line-suffix {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
}

/* ── Cost panel (admin Lustre view, Plan 12-04) ───────────────────────────── */

/* Full-width page column that replaces the workbench when "Costs" is active. */
.cost-screen {
  --gap: var(--space-8);
}

.cost-screen-inner {
  --gap: var(--space-8);
}

/* ── view/segment.gleam — the single-select chip row ─────────────────────────
   The row is the component's own recipe; its chips wear the shipped .run-chip
   family (also worn directly by the queue's multi-select filter chips). */
.segment-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* ── view/health_strip.gleam — quiet-when-ok status line ─────────────────────
   OK: one muted line with a small good-tone dot. NOT-OK: a loud danger-toned
   block, one line per failure (never softened or summarized). */
.health-strip {
  font-size: 0.8rem;
  color: var(--color-muted);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.health-ok-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-good);
  flex: none;
}

.health-strip.is-failing {
  display: block;
  color: var(--color-bad);
  border: 1px solid var(--color-bad);
  border-radius: var(--radius-2);
  padding: var(--space-3) var(--space-4);
  font-weight: 600;
}

.health-strip.is-failing .health-failure + .health-failure {
  margin-top: var(--space-1);
}

/* ── view/detail_pane.gleam — row drill-down frame ───────────────────────────
   Header (identity + lifecycle badges) · caller sections · lever row. Sits on
   the admin card surface, separated from the roster above by a rule. */
.detail-pane {
  border-top: 1px solid var(--color-line);
  padding-top: var(--space-5);
  --gap: var(--space-5);
}

.detail-head {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.detail-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--color-ink);
  margin: 0;
}

.detail-badges {
  display: flex;
  gap: var(--space-2);
}

.detail-badge {
  font: 700 var(--text-xs) var(--font-mono);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius-2);
  padding: 1px var(--space-2);
}

.detail-badge.is-danger {
  color: var(--color-bad);
  border-color: var(--color-bad);
}

.detail-badge.is-accent {
  color: var(--color-accent);
  border-color: var(--color-accent);
}

.detail-levers {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  border-top: 1px solid var(--color-line);
  padding-top: var(--space-4);
}

/* view/table.gleam row-click affordance (the .cost-table recipe below is the
   component's shared table skin). */
.table-row-click {
  cursor: pointer;
}

.table-row-click:hover td {
  background: color-mix(in srgb, var(--color-accent) 7%, transparent);
}

.table-row-click.is-active td {
  background: var(--color-selected);
}

/* Hero stat cluster — flat (no inner card chrome): it sits directly on the
   admin Card 1 surface, so a bordered/elevated hero would be a box-in-box.
   Two sibling stats (all-in spend + runs all-time) share the row, wrapping on
   narrow widths. */
.cost-hero {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-8) calc(var(--space-8) * 1.5);
}

.cost-hero-stat {
  display: grid;
  gap: var(--space-3);
  min-width: 0;
}

.cost-hero-total {
  font: 700 var(--text-2xl) var(--font-sans);
  line-height: 1;
  color: var(--color-accent);
}

.cost-hero-sub {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
}

/* `native · converted` money pairing (Phase 24, D-11). A pure layout wrapper
   for a paired money cell — children carry their own color/font. flex-wrap lets
   the native half drop onto its own line in a fixed-width table column
   ("wrap, don't lie"). */
.money-pair {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
  flex-wrap: wrap;
}

/* The muted, subordinate native figure in a pairing. Its text already carries a
   leading "· " (the middot lives in the text, not a separator element). Mono +
   tabular so it aligns with the primary; inherits the surrounding font-size at
   table-cell/inline scale. Never accent, never bold — must not compete. */
.money-native {
  color: var(--color-muted);
  font-weight: 400;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* Hero-scale override: sizes the native secondary down from the 2xl primary so
   it reads clearly subordinate by size as well as color. */
.money-native--hero {
  font-size: var(--text-md);
  line-height: 1;
}

/* The `(rate unavailable)` fallback suffix — a per-figure degrade when no FX
   observation backs a conversion. Muted, small, never fabricates a number. */
.money-unavailable-note {
  color: var(--color-muted);
  font: 400 var(--text-xs) var(--font-sans);
  margin-left: var(--space-1);
}

/* Estimate legend (in the hero + as a footnote above the tables). */
.cost-legend {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.cost-legend-text {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
}

.cost-legend-footnote {
  margin-top: calc(-1 * var(--space-4));
}

/* EST / EXACT badge — same color-mix treatment as .verify-badge, weight 700. */
.cost-badge {
  flex: 0 0 auto;
  border-radius: var(--radius-1);
  padding: 1px var(--space-2);
  font: 700 var(--text-xs) var(--font-mono);
  letter-spacing: 0.06em;
}

.cost-badge.is-est {
  background: color-mix(in srgb, var(--color-warn) 20%, transparent);
  color: color-mix(in srgb, var(--color-warn) 68%, var(--color-ink));
}

.cost-badge.is-exact {
  background: color-mix(in srgb, var(--color-good) 18%, transparent);
  color: color-mix(in srgb, var(--color-good) 68%, var(--color-ink));
}

/* Stacked breakdown sections. */
.cost-breakdown {
  --gap: var(--space-6);
}

.cost-section {
  --gap: var(--space-3);
}

/* Breakdown table. */
.cost-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  table-layout: fixed;
}

.cost-table th {
  font: 700 var(--text-xs) var(--font-mono);
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-line-strong);
}

.cost-table th.col-num {
  text-align: right;
}

.cost-table td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-line);
  color: var(--color-ink);
  font-weight: 400;
}

.cost-table td.col-num {
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.cost-table td.col-mono {
  font-family: var(--font-mono);
}

.cost-table td.col-truncate {
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.cost-table tr:last-child td {
  border-bottom: 0;
}

.cost-empty-row {
  text-align: center;
  color: var(--color-muted);
}

/* Unknown-model footnote beneath the by-run table. */
.cost-footnote {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
}

/* Loading-state placeholder cell. */
.cost-skeleton {
  height: 0.9rem;
  border-radius: var(--radius-1);
  background: var(--color-line);
  opacity: 0.6;
}

/* Admin Costs nav button in the topbar. */
.nav-tab {
  border: 0;
  background: transparent;
  color: var(--color-ink-soft);
  font: 700 var(--text-sm) var(--font-sans);
  cursor: pointer;
  padding: 0 var(--space-2);
}

.nav-tab:hover {
  color: var(--color-ink);
}

.nav-tab.is-active {
  color: var(--color-accent);
}

@media (max-width: 780px) {
  .target-form {
    --columns: 1;
    grid-template-columns: 1fr;
  }

  .target-actions {
    align-items: stretch;
    flex-direction: column;
  }

  .run-row {
    align-items: flex-start;
    flex-direction: column;
    gap: var(--space-2);
  }
}

@media (max-width: 960px) {
  .detail-drawer {
    inset: 0 0 0;
    width: 100vw;
    border-left: 0;
    box-shadow: none;
  }

  .detail-drawer > * {
    width: 100%;
  }
}

/* Login — a single centered card on the paper gradient. Inputs and the submit
   button mirror the workbench's .field / .button so the gate feels like the app. */
.login-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: var(--space-6);
}

.login-card {
  width: 100%;
  max-width: 380px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-surface-raised);
  box-shadow: var(--shadow-soft);
  padding: var(--space-8);
}

.login-title {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--text-2xl);
}

.login-lede {
  margin: var(--space-2) 0 0;
  color: var(--color-muted);
  font-size: var(--text-sm);
}

.login-form {
  display: grid;
  gap: var(--space-4);
  margin-top: var(--space-6);
}

.login-field {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
}

.login-field label {
  color: var(--color-muted);
  font: 600 var(--text-sm) var(--font-sans);
}

.login-field input {
  width: 100%;
  min-height: 48px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-surface);
  color: var(--color-ink);
  padding: 0 var(--space-4);
  outline: none;
}

.login-field input:focus {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}

.login-submit {
  min-height: 48px;
  width: 100%;
  margin-top: var(--space-2);
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-2);
  background: var(--color-ink);
  color: var(--color-surface);
  font-weight: 700;
  font-size: var(--text-sm);
}

.login-submit:hover {
  background: color-mix(in srgb, var(--color-ink) 84%, var(--color-accent));
}

.login-submit:disabled {
  opacity: 0.62;
  cursor: not-allowed;
}

/* Row of secondary mode-switch links under the login form (Phase 20 —
   Password mode's "Email me a sign-in code instead" / "Forgot password?",
   and the single back-link in the two request modes). */
.login-links {
  display: flex;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-2);
}

/* The 6-digit sign-in code input (CodeMode step 2, quick 260710-p43):
   inherits .login-field input's box; the modifier makes the typed code read
   as a code — large, centered, monospace, letter-spaced. */
.login-code-input {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--text-lg);
  letter-spacing: 0.4em;
  text-align: center;
}

/* Signup screen (Phase 21, Surface 1). .signup-card is a width modifier used
   alongside .login-card (class="login-card signup-card") — the same pairing
   pattern as .auth-modal alongside .cost-modal. .login-form-row pairs First
   name / Last name into a 2-col grid, the form's only two-column row.
   .login-footer is the shared "switch between login <-> signup" row, used on
   both screens. Zero new tokens. */
.signup-card {
  max-width: 460px;
}

.login-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

.login-footer {
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-line);
  text-align: center;
  font: 400 var(--text-xs) var(--font-sans);
  color: var(--color-muted);
}

/* PMS typeahead combobox (Phase 21, Surface 2) — the phase's one net-new
   interaction, built entirely from existing recipes: .login-field input (the
   text input), .admin-user-row (each option row), .admin-empty (the no-match
   row), and .cost-modal's surface/border/shadow treatment (the popover box,
   repositioned as an absolute popover instead of a fixed-centered modal). */
.pms-combobox {
  position: relative;
}

.pms-combobox-input {
  width: 100%;
  min-height: 48px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-surface);
  color: var(--color-ink);
  padding: 0 var(--space-4);
  outline: none;
}

.pms-combobox-input:focus {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}

.pms-combobox-list {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  right: 0;
  z-index: 10;
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-surface-raised);
  box-shadow: var(--shadow-soft);
}

.pms-combobox-option {
  display: flex;
  align-items: center;
  padding: var(--space-3) var(--space-4);
  font: 400 var(--text-sm) var(--font-sans);
  cursor: pointer;
  transition: background 120ms ease;
}

.pms-combobox-option:hover {
  background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}

.pms-combobox-option.is-highlighted {
  background: color-mix(in srgb, var(--color-accent) 16%, var(--color-surface));
}

.pms-combobox-empty {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
  padding: var(--space-4);
}

/* Cost panel modal overlay. The layer centers the card on a scrim; the backdrop
   is a sibling of the card (not its parent) so clicks inside the card never
   bubble to the close handler — only the scrim and the X close it. The card
   scrolls internally so a tall breakdown never overflows the viewport. */
.cost-modal-layer {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: var(--space-6);
}

.cost-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 16, 12, 0.46);
  backdrop-filter: blur(1.5px);
}

.cost-modal {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 820px;
  max-height: 86vh;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-canvas);
  box-shadow: var(--shadow-drawer);
  overflow: hidden;
}

.cost-modal-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--color-line);
  background: var(--color-surface);
}

.cost-modal-title {
  margin: 0;
  font-family: var(--font-serif);
  font-size: var(--text-xl);
}

.cost-modal-close {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-surface-raised);
  color: var(--color-ink-soft);
  font-size: var(--text-md);
  line-height: 1;
}

.cost-modal-close:hover {
  color: var(--color-ink);
  border-color: var(--color-line-strong);
  background: var(--color-selected);
}

.cost-modal-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--space-6);
}

/* Set-password modal (Phase 20, Surface 4) — shrinks the 820px cost-modal
   width down to a single-field form's proportions. Used alongside .cost-modal
   (class="cost-modal auth-modal"); no other cost-modal rule changes. */
.auth-modal {
  max-width: 420px;
}

/* In-app feedback modal (260707-kug) — reuses .cost-modal.auth-modal chrome
   verbatim and .ledger-adjust-reason's text-input treatment for the message
   field; these are the only new rules, for the multi-line textarea sizing
   and the opt-in screenshot preview. */
.feedback-message-input {
  min-height: 120px;
  padding: var(--space-3);
  resize: vertical;
  font-family: var(--font-sans);
}

.feedback-screenshot-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font: 400 var(--text-sm) var(--font-sans);
}

.feedback-screenshot-helper {
  margin: 0;
  font: 400 var(--text-xs) var(--font-sans);
  color: var(--color-muted);
}

.feedback-screenshot-preview {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.feedback-screenshot-thumb {
  max-width: 220px;
  max-height: 140px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  object-fit: contain;
}

/* The message is the point of the feedback list: allow a few wrapped lines
   before clamping (full text on the title tooltip) instead of a one-line cut. */
.feedback-message {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* ── Phase 17 admin + billing + topbar design pass ── */

/* Topbar — three-zone layout */
.topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.topbar-zone {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.topbar-zone--nav {
  gap: var(--space-3);
}

.topbar-divider {
  width: 1px;
  align-self: stretch;
  margin-block: var(--space-3);
  background: var(--color-line);
}

/* Clickable wordmark — no visual change to the text; resets button chrome */
.app-brand--link {
  cursor: pointer;
  border: 0;
  background: transparent;
  text-decoration: none;
}

/* Sign out — quiet account action (lowest emphasis) */
.nav-signout {
  border: 0;
  background: transparent;
  color: var(--color-muted);
  font: 400 var(--text-sm) var(--font-sans);
  cursor: pointer;
  padding: 0 var(--space-2);
}

.nav-signout:hover {
  color: var(--color-ink);
}

/* Buy-runs text link — understated inline action beside the balance count */
.buy-cluster {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.nav-buy-link {
  border: 0;
  background: transparent;
  color: var(--color-muted);
  font: 400 var(--text-sm) var(--font-sans);
  cursor: pointer;
  padding: 0 var(--space-2);
  text-decoration: none;
}

.nav-buy-link:hover {
  color: var(--color-ink);
}

/* Commerce CTA — real bordered button */
.nav-tab--cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  font: 700 var(--text-sm) var(--font-sans);
  padding: 0 var(--space-4);
  border: 1px solid color-mix(in srgb, var(--color-accent) 50%, transparent);
  border-radius: var(--radius-2);
  background: transparent;
  color: var(--color-accent);
  cursor: pointer;
}

.nav-tab--cta:hover {
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  border-color: var(--color-accent);
}

.nav-tab--cta:active {
  background: color-mix(in srgb, var(--color-accent) 20%, transparent);
}

.nav-tab--cta:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  background: transparent;
}

/* ── Impersonation exception state (Phase 23, Surface 2, SC-2) ──────────────
   While impersonating, the WHOLE topbar adopts a warn tint + a 2px warn bottom
   border so the mode is genuinely loud and unmissable on every route (not a
   subtle badge relabel). Zone D holds the "Viewing as {name}" badge + a real
   bordered one-click Exit. Repurposes the existing --color-warn token as the
   dedicated "exceptional operating mode" signal — zero new tokens. */
.app-topbar.is-impersonating {
  background: color-mix(in srgb, var(--color-warn) 16%, var(--color-canvas));
  border-bottom: 2px solid var(--color-warn);
}

.topbar-zone--impersonation {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.impersonation-badge {
  border: 1px solid var(--color-warn);
  border-radius: var(--radius-2);
  background: color-mix(in srgb, var(--color-warn) 14%, transparent);
  color: var(--color-warn);
  font: 700 var(--text-sm) var(--font-sans);
  padding: var(--space-1) var(--space-3);
}

.impersonation-exit {
  border: 1px solid var(--color-warn);
  background: transparent;
  color: var(--color-warn);
  font: 700 var(--text-xs) var(--font-sans);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-2);
  cursor: pointer;
}

.impersonation-exit:hover {
  background: color-mix(in srgb, var(--color-warn) 18%, transparent);
}

/* ── Mollyguard override block (Phase 23, Surface 3, IMP-04/D-08) ────────────
   ONE inline reason-gated exception block, revealed at the point of a blocked
   dangerous action while impersonating. Same warn-tint family as the topbar
   exception state (tying the two together as one visual language); reuses the
   shipped .ledger-adjust(-reason) input row for the reason field. Grid stack
   (heading + body + input row), unlike .notice--block's single-row shape. Zero
   new tokens. */
.mollyguard-block {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid color-mix(in srgb, var(--color-warn) 40%, var(--color-line));
  border-radius: var(--radius-2);
  background: color-mix(in srgb, var(--color-warn) 12%, var(--color-surface));
  color: var(--color-warn);
}

.mollyguard-heading {
  font: 700 var(--text-sm) var(--font-sans);
}

.mollyguard-body {
  font: 400 var(--text-sm) var(--font-sans);
  line-height: 1.5;
}

/* Proceed — identical shape to .ledger-adjust-apply, recolored warn. */
.mollyguard-confirm {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 var(--space-4);
  font: 700 var(--text-sm) var(--font-sans);
  border: 1px solid color-mix(in srgb, var(--color-warn) 50%, transparent);
  border-radius: var(--radius-2);
  background: transparent;
  color: var(--color-warn);
  cursor: pointer;
}

.mollyguard-confirm:hover {
  background: color-mix(in srgb, var(--color-warn) 12%, transparent);
  border-color: var(--color-warn);
}

.mollyguard-confirm:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  background: transparent;
}

/* Balance chip */
.nav-balance {
  font: 700 var(--text-sm) var(--font-sans);
  color: var(--color-ink);
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
  padding: 0;
}

.nav-balance.is-low {
  color: var(--color-warn);
}

.nav-balance-owed {
  font: 400 var(--text-xs) var(--font-sans);
  color: var(--color-bad);
  margin-left: var(--space-1);
}

/* Admin screen wrapper */
.admin-screen {
  --gap: var(--space-8);
  padding-top: var(--space-8);
  padding-bottom: var(--space-8);
  /* NO horizontal padding: .l-container owns the width, so the cards align
     EXACTLY with the header/queue content line (the locked-in rail). */
}

@media (max-width: 600px) {
  .admin-screen {
    padding-inline: var(--space-4);
  }
}

/* Admin block card */
.admin-block {
  display: grid;
  --gap: var(--space-4);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-surface-raised);
  padding: var(--space-5) var(--space-6);
  box-shadow: var(--shadow-soft);
}

/* User picker dropdown */
.admin-select {
  width: 100%;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-surface);
  color: var(--color-ink);
  font: 400 var(--text-sm) var(--font-sans);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
}

.admin-select:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}

/* User picker (legacy list, kept for reference) */
.admin-user-list {
  display: grid;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  overflow: hidden;
}

.admin-user-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 0;
  border-bottom: 1px solid var(--color-line);
  background: transparent;
  color: var(--color-ink);
  cursor: pointer;
  text-align: left;
  width: 100%;
  font: 400 var(--text-sm) var(--font-sans);
  transition: background 120ms ease;
}

.admin-user-row:last-child {
  border-bottom: 0;
}

.admin-user-row:hover {
  background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}

.admin-user-row.is-selected {
  background: color-mix(in srgb, var(--color-accent) 16%, var(--color-surface));
}

.admin-user-row.is-selected:hover {
  background: color-mix(in srgb, var(--color-accent) 20%, var(--color-surface));
}

.admin-user-row.is-disabled {
  cursor: default;
  opacity: 0.55;
  pointer-events: none;
  background: transparent;
}

.admin-user-name {
  font-weight: 700;
}

.admin-user-meta {
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--color-muted);
}

/* Promote-to-admin USERS card (Phase 19, D-05, IDENT-04) — a static display
   row with a trailing action, NOT the clickable-row selector above. Visually
   matches .admin-user-list/.admin-user-row but gets its own thin class set
   since the whole row is not interactive (only the trailing action is). */
.user-role-list {
  display: grid;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  overflow: hidden;
}

.user-role-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-line);
}

.user-role-row:last-child {
  border-bottom: 0;
}

.user-role-name {
  font: 700 var(--text-sm) var(--font-sans);
  color: var(--color-ink);
}

.role-badge {
  font: 700 var(--text-xs) var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-1);
  border: 1px solid;
}

.role-badge.is-admin {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

/* SUSPENDED pill (Phase 23) — sibling of .is-admin, destructive tone. */
.role-badge.is-suspended {
  border-color: var(--color-bad);
  color: var(--color-bad);
}

.role-meta {
  font: 400 var(--text-xs) var(--font-mono);
  text-transform: uppercase;
  color: var(--color-muted);
}

/* ── Ledger element ──────────────────────────────────────────────────────────
   ONE cohesive card: total header → pinned adjust row → scrolling entries.
   Spacing scale climbs in deliberate steps (space-3 within a row, space-5
   between the total/adjust/entries sections) so the element reads as crafted,
   not cramped. The total + adjust row stay anchored while older entries scroll. */
.ledger {
  display: grid;
  gap: var(--space-5);
}

/* 1. Total — the running sum IS the balance; this is the headline. It reuses
   the spend card's .cost-hero-stat / .cost-hero-total / .cost-hero-sub styling
   so both cards' big figures match. Only the deficit sub-label is bespoke. */
.ledger-total-owed {
  font: 600 var(--text-sm) var(--font-sans);
  color: var(--color-bad);
}

/* 2. Inline adjust row — compact, single row, pinned under the total. */
.ledger-adjust {
  display: flex;
  align-items: stretch;
  gap: var(--space-2);
}

.ledger-adjust-delta,
.ledger-adjust-reason {
  min-height: 40px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-surface);
  color: var(--color-ink);
  padding: 0 var(--space-3);
  font: 400 var(--text-sm) var(--font-sans);
  outline: none;
}

.ledger-adjust-delta {
  flex: 0 0 7.5rem;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.ledger-adjust-reason {
  flex: 1 1 auto;
  min-width: 0;
}

.ledger-adjust-delta::placeholder,
.ledger-adjust-reason::placeholder {
  color: var(--color-muted);
}

.ledger-adjust-delta:focus,
.ledger-adjust-reason:focus {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}

.ledger-adjust-apply {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 var(--space-4);
  font: 700 var(--text-sm) var(--font-sans);
  border: 1px solid color-mix(in srgb, var(--color-accent) 50%, transparent);
  border-radius: var(--radius-2);
  background: transparent;
  color: var(--color-accent);
  cursor: pointer;
}

.ledger-adjust-apply:hover {
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  border-color: var(--color-accent);
}

.ledger-adjust-apply:active {
  background: color-mix(in srgb, var(--color-accent) 20%, transparent);
}

.ledger-adjust-apply:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  background: transparent;
}

/* 3. Entries — newest-first, scrolling so the total + input stay anchored. */
.ledger-entries {
  display: grid;
  max-height: 22rem;
  overflow-y: auto;
  border-top: 1px solid var(--color-line-strong);
}

.ledger-row {
  display: grid;
  grid-template-columns: 1fr auto 4.5rem;
  align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-1);
  border-bottom: 1px solid var(--color-line);
}

.ledger-row:last-child {
  border-bottom: 0;
}

/* Activity column — folds kind (label) + reason (detail) into one cell. */
.ledger-cell-activity {
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.ledger-activity-kind {
  font: 600 var(--text-sm) var(--font-sans);
  color: var(--color-ink);
}

.ledger-activity-detail {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
}

.ledger-cell-amount {
  justify-self: end;
  text-align: right;
  font: 600 var(--text-sm) var(--font-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ledger-cell-amount.is-credit {
  color: var(--color-good);
}

.ledger-cell-amount.is-debit {
  color: var(--color-ink-soft);
}

.ledger-cell-when {
  justify-self: end;
  text-align: right;
  font: 400 var(--text-xs) var(--font-mono);
  color: var(--color-muted);
  white-space: nowrap;
}

.ledger-empty {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
  padding: var(--space-6) var(--space-1);
  text-align: center;
}

/* Per-user card 2 — extra breathing room between picker → switcher → ledger. */
.admin-card2 {
  --gap: var(--space-6);
}

/* Empty and hint states */
.admin-empty {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
  padding: var(--space-4) 0;
}

.admin-hint {
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-muted);
  line-height: 1.5;
}

/* ── Toasts ──────────────────────────────────────────────────────────────────
   Ephemeral billing notices (run spent / no runs left). Fixed bottom-right
   stack, newest on top. The region lets clicks pass through its gaps; each
   toast re-enables pointer events for its dismiss control. */
.toast-region {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: min(360px, calc(100vw - 2 * var(--space-6)));
  pointer-events: none;
}

/* Same tinted-box recipe as .notice--block (shared --tone-color), so toasts and
   inline notices read as one family. A toast just adds elevation (shadow) and
   the entry animation since it floats over the page. NO accent border. */
.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid color-mix(in srgb, var(--tone-color) 40%, var(--color-line));
  background: color-mix(in srgb, var(--tone-color) 12%, var(--color-surface));
  color: var(--tone-color);
  border-radius: var(--radius-2);
  box-shadow: var(--shadow-soft);
  font: 400 var(--text-sm) var(--font-sans);
  animation: toast-in 160ms ease-out;
}

.toast-info {
  --tone-color: var(--color-info);
}

.toast-success {
  --tone-color: var(--color-good);
}

.toast-warn {
  --tone-color: var(--color-warn);
}

.toast-danger {
  --tone-color: var(--color-bad);
}

.toast-message {
  flex: 1 1 auto;
  line-height: 1.4;
}

.toast-dismiss {
  flex: 0 0 auto;
  appearance: none;
  border: none;
  background: transparent;
  color: inherit;
  opacity: 0.6;
  font-size: var(--text-lg);
  line-height: 1;
  padding: 0 var(--space-1);
  cursor: pointer;
  transition: opacity 120ms ease;
}

.toast-dismiss:hover {
  opacity: 1;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .toast {
    animation: none;
  }
}

@media (max-width: 600px) {
  .toast-region {
    right: var(--space-4);
    left: var(--space-4);
    bottom: var(--space-4);
    max-width: none;
  }
}

/* ── Account page (Phase 22) ───────────────────────────────────────────────
   All net-new classes are one-line variations on existing selectors, built
   from existing tokens only (zero new token values). See 22-UI-SPEC.md
   "New CSS — Consolidated". */

/* Surface 1 — top-bar user-menu dropdown (Zone C) */
.user-menu {
  position: relative;
}

/* verbatim .nav-signout font/color + single-line truncation for a long email */
.user-menu-trigger {
  border: 0;
  background: transparent;
  color: var(--color-muted);
  font: 400 var(--text-sm) var(--font-sans);
  cursor: pointer;
  padding: 0 var(--space-2);
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-menu-trigger:hover {
  color: var(--color-ink);
}

/* verbatim .pms-combobox-list, mirrored to hang from the right edge */
.user-menu-list {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  left: auto;
  z-index: 10;
  min-width: 10rem;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  background: var(--color-surface-raised);
  box-shadow: var(--shadow-soft);
}

/* verbatim .admin-user-row / .pms-combobox-option row button */
.user-menu-item {
  display: flex;
  width: 100%;
  padding: var(--space-3) var(--space-4);
  font: 400 var(--text-sm) var(--font-sans);
  color: var(--color-ink);
  cursor: pointer;
  text-align: left;
  background: transparent;
  border: 0;
}

.user-menu-item:hover {
  background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}

.user-menu-divider {
  border-top: 1px solid var(--color-line);
  margin: var(--space-1) 0;
}

/* Surface 3 — Profile section */
.acct-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.acct-field-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0;
}

.acct-field-label {
  color: var(--color-muted);
  font: 400 var(--text-sm) var(--font-sans);
}

.acct-field-value {
  color: var(--color-ink);
  font: 400 var(--text-sm) var(--font-sans);
  text-align: right;
}

/* Surface 5 — Billing section (badged ledger). .acct-ledger-amount / -when /
   -link / -empty are the EXISTING .ledger-cell-amount / .ledger-cell-when /
   .text-link / .ledger-empty reused verbatim — no duplicate selectors here. */
.acct-ledger {
  display: grid;
  gap: var(--space-5);
}

.acct-ledger-head {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: var(--space-4);
  padding: 0 var(--space-1) var(--space-2);
  font: 700 var(--text-xs) var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-muted);
  border-bottom: 1px solid var(--color-line-strong);
}

.acct-ledger-row {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  align-items: start;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-1);
  border-bottom: 1px solid var(--color-line);
}

.acct-ledger-row:last-child {
  border-bottom: 0;
}

.acct-ledger-activity {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}

/* verbatim .run-status box shape; color modifiers below follow its
   single-property .is-active / .is-complete / .is-review pattern */
.ledger-badge {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-canvas);
  padding: var(--space-1) var(--space-2);
  font: 700 var(--text-xs) var(--font-mono);
  width: fit-content;
}

.ledger-badge.is-grant {
  color: var(--color-info);
}

.ledger-badge.is-purchase {
  color: var(--color-good);
}

.ledger-badge.is-charge {
  color: var(--color-ink-soft);
}

.ledger-badge.is-adjustment {
  color: var(--color-warn);
}

.acct-ledger-sub {
  font: 400 var(--text-xs) var(--font-sans);
  color: var(--color-muted);
}

.acct-ledger-balance {
  justify-self: end;
  text-align: right;
  font: 400 var(--text-sm) var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--color-muted);
  white-space: nowrap;
}

/* ── Revenue & margin analytics (Phase 25) ───────────────────────────────────
   The sparkline-card surface: an immersive Gross-margin hero above six squarish
   stat cards, each with a data-driven mini trend line. Token-disciplined
   translation of .planning/sketches/v2.4-admin-analytics/revenue-margin.html +
   spark.css (mockup's ad-hoc :root literals mapped to tokens.css). */
/* The shared scaffold frame (view/scaffold.gleam) — all three admin views
   wear .admin-screen; the old per-page scopes are folded onto it. */
/* Width comes from .l-container (the shared content rail) — no local
   max-width, so admin can never drift from the header/queue line. */
/* Inner card-field stacks (the Metrics hero/stats/breakdown column and the
   Users drill-down pane) run at the SAME 16px rhythm as the card grid's
   gap; the page-level stack keeps 32px between sections. Two steps on one
   scale — nothing in between. */
.admin-screen .metrics-stack,
.admin-screen .detail-pane {
  --gap: var(--space-4);
}

/* The scaffold's single header row: the sub-nav segment (the understated
   page title) on the left, the optional controls (range segment) on the
   right — one visual level, no h1. */
.admin-screen .scaffold-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  /* No local margin: the l-stack gap owns ALL vertical rhythm (16 inside
     the grid, 32 between sections — one scale, no drift). */
}
.admin-screen .subtle-note {
  font-size: 0.78rem;
  color: var(--color-muted);
  margin-bottom: 22px;
}

/* The top-right range selector — small chips, active reflects the loaded range. */
.range {
  display: flex;
  gap: 4px;
  align-items: center;
}
.range .chip {
  padding: 4px 10px;
  border-radius: var(--radius-2);
  font-size: 0.8rem;
  color: var(--color-ink-soft);
  cursor: pointer;
  border: 1px solid transparent;
  background: transparent;
  font-family: var(--font-sans);
}
.range .chip:hover {
  background: var(--color-selected);
}
.range .chip.active {
  background: var(--color-canvas-warm);
  border-color: var(--color-line-strong);
  color: var(--color-ink);
  font-weight: 600;
}

/* 4-column grid; the hero spans two, fixed card row height. */
.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  grid-auto-rows: 172px;
}
/* The hero row needs its own height: 18px pad + label + 2.9rem value + sub
   + the 64px hero spark is ~200px — inside a 172px row the card cropped the
   BOTTOM ~28px of the hero sparkline (overflow: hidden), which cut off
   exactly the negative/red region of signed margin charts. Only grids that
   actually open with heroes get the taller first row (the Users drill-down
   grid has no heroes and keeps uniform 172px rows). */
.grid:has(.fig.hero) {
  grid-template-rows: 204px;
}
/* ── view/card.gleam — the stat card ─────────────────────────────────────────
   .fig / .k / .v / .sub / .spark: label · big value (pos/neg tone, optional
   money-code addon) · sub-line · hover-scrub sparkline; .fig.hero spans 2. */
.fig {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  box-shadow: var(--shadow-soft);
  padding: 18px 18px 0;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}
/* The no-sparkline lever/status card variant (card.lever): bottom padding
   restored (no flush trend), actions row pinned to the bottom edge. */
.fig.lever {
  padding-bottom: 16px;
}
.fig.lever .card-actions {
  margin-top: auto;
  padding-top: 10px;
  display: flex;
  align-items: center;
  gap: 6px;
}
/* The whole open edit form (input + Save + Never mind) fits ONE compact row
   inside the fixed 172px card — nothing wraps, nothing clips. */
.fig.lever .card-actions .ledger-adjust-delta {
  flex: 0 1 64px;
  width: 64px;
  min-width: 0;
  padding-inline: 8px;
}
.fig.lever .card-actions .run-chip {
  padding-inline: 8px;
  white-space: nowrap;
}
.fig.hero {
  grid-column: span 2;
}
.fig .k {
  font-size: 0.75rem;
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
}
.fig .v {
  font-family: var(--font-mono);
  font-size: 2rem;
  letter-spacing: -0.02em;
  margin-top: 8px;
  line-height: 1;
  color: var(--color-ink);
}
.fig.hero .v {
  font-size: 2.9rem;
  margin-top: 12px;
}
.fig .v.pos {
  color: var(--color-good);
}
.fig .v.neg {
  color: var(--color-bad);
}
.fig .sub {
  font-size: 0.78rem;
  color: var(--color-ink-soft);
  margin-top: 6px;
  font-family: var(--font-mono);
}
.fig .sub.muted {
  color: var(--color-muted);
}
.fig .sub.pos {
  color: var(--color-good);
}
.fig .sub.neg {
  color: var(--color-bad);
}
/* flex-basis (not height) + shrink so the spark GIVES UP height instead of
   overflowing the card bottom when the content above runs tall — under
   .fig { overflow: hidden } an overflowing spark is silently cropped, which
   ate the bottom of the chart (the negative region of signed series). The
   svg stretches (preserveAspectRatio="none"), so any rendered height works. */
.fig .spark {
  margin: auto -18px 0;
  flex: 0 1 52px;
  height: auto;
  min-height: 0;
}
.fig.hero .spark {
  flex-basis: 64px;
}
.fig .spark svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

/* Sparkline geometry classes (mirrors spark.css; only the g/a colours used). */
.sline {
  fill: none;
  stroke-width: 1.6;
}
/* Area fills are theme-aware gradients (defs emitted inside every sparkline
   SVG): full tint at the line fading to transparent at the fill's own
   baseline — the card bottom for positive/unsigned areas, the zero line for
   signed negative ones (`.neg` -> the upward fade). Alpha lives in the
   gradient stops (0.25 -> 0), so no element-level opacity here. */
.sarea {
  opacity: 1;
}
/* Runs/day volume underlay (metrics hero only): faint neutral bars behind the
   rate line so a low % reads as noise-or-signal at a glance. */
.svol {
  fill: var(--color-muted);
  opacity: 0.16;
}
.sdot {
  transition: opacity 0.1s;
}
.sline.g {
  stroke: var(--color-good);
}
.sarea.g {
  fill: url(#sgrad-g-down);
}
.gstop-g {
  stop-color: var(--color-good);
}
.sdot.g {
  fill: var(--color-good);
}
/* Regal blue: absolute counts (not a money verdict, not a status tone). */
.sline.b {
  stroke: var(--color-figure);
}
.sarea.b {
  fill: url(#sgrad-b-down);
}
.gstop-b {
  stop-color: var(--color-figure);
}
.sdot.b {
  fill: var(--color-figure);
}

/* Cross-card hover scrub: a short dashed crosshair rising from the baseline to
   the hovered dot, and the hover dot colored to match the card's own chart
   color at the scrubbed day. */
.xhair {
  stroke: var(--color-line-strong);
  stroke-width: 1;
  stroke-dasharray: 2 3;
}
.hdot.g {
  fill: var(--color-good);
}
.hdot.b {
  fill: var(--color-figure);
}

.globalnote {
  font-size: 0.74rem;
  color: var(--color-muted);
  margin-top: 16px;
  font-style: italic;
  text-align: center;
}
.revenue-degrade {
  padding: 32px 0;
  text-align: center;
  color: var(--color-muted);
  font-size: 0.9rem;
}

/* ── Run outcomes / north-star (Phase 26) ─────────────────────────────────────
   The immersive hero (success rate % over its own area trend + delta) above
   three `.fig` sparkline stat cards (reused verbatim from Revenue) and an
   outcome breakdown bar + legend. Token-disciplined translation of
   .planning/sketches/v2.4-admin-analytics/run-outcomes-northstar.html. */
.admin-screen .subtle-note {
  font-size: 0.78rem;
  color: var(--color-muted);
  margin-bottom: 22px;
}

/* Generic bordered card base (the mockup's `.card`) — the hero and the
   breakdown card both compose onto this; the three stat cards use `.fig`'s
   own equivalent recipe instead (reused from Revenue, no card-within-card).
   Namespaced under `.admin-screen` (Metrics page) (IN-03): `.card`/`.hero`/`.herotop`/
   `.big`/`.delta`/`.lbl`/`.desc` are generic enough that a future view could
   reuse the same class name for a different visual recipe — scoping matches
   this file's own `.metrics-grid`/`.obar`/`.oseg`/`.okeys` convention. */
.admin-screen .card {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-3);
  box-shadow: var(--shadow-soft);
}

/* The immersive hero: big success-rate % + label/description + delta, over
   its own full-width area trend (rendered via the reused `.spark` engine). */
/* The Metrics page's bespoke immersive hero (.card.hero) ONLY — scoped so
   it never bleeds onto the stat-card grid's .fig.hero, whose geometry the
   grid track owns. NO margin: the enclosing stack owns vertical rhythm. */
.admin-screen .card.hero {
  position: relative;
  overflow: hidden;
  padding: 24px 26px 0;
}
.admin-screen .herotop {
  display: flex;
  align-items: flex-start;
  gap: 26px;
  position: relative;
  z-index: 2;
}
.admin-screen .hero .big {
  font-family: var(--font-mono);
  font-size: 3.4rem;
  letter-spacing: -0.03em;
  line-height: 0.95;
  color: var(--color-ink);
}
.admin-screen .hero .big.pos {
  color: var(--color-good);
}
.admin-screen .hero .lbl {
  font-size: 0.8rem;
  color: var(--color-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}
.admin-screen .hero .desc {
  font-size: 1.02rem;
  color: var(--color-ink-soft);
  margin-top: 5px;
  max-width: 470px;
}
.admin-screen .hero .delta {
  margin-left: auto;
  text-align: right;
  font-family: var(--font-mono);
}
.admin-screen .hero .delta .d {
  font-size: 1.15rem;
}
.admin-screen .hero .delta .d.pos {
  color: var(--color-good);
}
.admin-screen .hero .delta .d.neg {
  color: var(--color-bad);
}
.admin-screen .hero .delta .dl {
  font-size: 0.74rem;
  color: var(--color-muted);
  font-family: var(--font-sans);
  margin-top: 2px;
}
/* The hero's own reused `.spark` (revenue.sparkline) — stretched full-bleed
   under `.herotop`, mirroring the mockup's `.herochart` sizing. Scoped to the
   Metrics bespoke `.card.hero` ONLY: the bare `.hero .spark` form also
   matched the stat grid's `.fig.hero .spark` (3 classes beat `.fig .spark`'s
   2) and its `margin-top: 14px` overrode the flush-bottom `margin-top: auto`,
   floating the hero sparkline 10px above the card bottom — the same
   class-bleed trap the unscoped `.admin-screen .hero` margin hit before. */
.admin-screen .card.hero .spark {
  margin: 14px -26px 0;
  height: 120px;
  width: calc(100% + 52px);
}

/* The 3-up sparkline stat card grid (Reached someone / No route found / Avg
   reachable per run) — `.fig` itself is Revenue's reused recipe; only the
   column count differs from Revenue's 4-column `.grid`. */
.metrics-grid {
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 168px;
}

/* The "no route found" sparkline colour (Revenue only ported g/a). */
.sline.c {
  stroke: var(--color-bad);
}
.sarea.c {
  fill: url(#sgrad-c-down);
}
.sarea.c.neg {
  fill: url(#sgrad-c-up);
}
.gstop-c {
  stop-color: var(--color-bad);
}
.sdot.c {
  fill: var(--color-bad);
}
.hdot.c {
  fill: var(--color-bad);
}

/* The outcome breakdown: a segmented bar + 4-key legend. No Phase-25 analog
   — hovering a segment or its legend key highlights the pair (`.oc-hot`) and
   dims the rest (`.oc-dim`). */
.cardpad {
  padding: 20px 24px;
}
.obar {
  display: flex;
  height: 14px;
  border-radius: 7px;
  overflow: hidden;
  margin-bottom: 16px;
  cursor: default;
  transition: opacity 0.12s;
}
.oseg {
  transition: opacity 0.12s;
}
.oseg.o1 {
  background: var(--color-good);
}
.oseg.o2 {
  background: color-mix(in srgb, var(--color-good) 50%, var(--color-canvas));
}
.oseg.o3 {
  background: var(--color-info);
}
.oseg.o4 {
  background: color-mix(in srgb, var(--color-bad) 45%, var(--color-canvas));
}
.okeys {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}
.okey {
  cursor: default;
  transition: opacity 0.12s;
}
.okey .n {
  font-family: var(--font-mono);
  font-size: 1.15rem;
  color: var(--color-ink);
}
.okey .t {
  font-size: 0.76rem;
  color: var(--color-muted);
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 2px;
}
.okey .t i {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  display: inline-block;
  font-style: normal;
}
.k1 {
  background: var(--color-good);
}
.k2 {
  background: color-mix(in srgb, var(--color-good) 50%, var(--color-canvas));
}
.k3 {
  background: var(--color-info);
}
.k4 {
  background: color-mix(in srgb, var(--color-bad) 45%, var(--color-canvas));
}
.okey.oc-hot .t {
  color: var(--color-ink);
  font-weight: 600;
}
.okey.oc-hot .n {
  color: var(--color-ink);
}
.oc-dim {
  opacity: 0.34;
}

/* ── Money figure (view/money.gleam) ──────────────────────────────────────────
   Symbol-first amount ("£37.07", "$1.62") with a small always-visible ISO-code
   tag. Sized in em so it scales from hero figures down to table cells, with a
   floor so it never becomes unreadable; currentColor keeps it legible on
   toned (pos/neg) values. */
.money-figure {
  display: inline-flex;
  align-items: baseline;
}
.money-code {
  /* The space lives on the tag (not a parent flex gap) so it holds wherever
     the tag renders — inside .money-figure or as a sibling in a card value. */
  margin-left: 0.55em;
  font-size: max(0.3em, 9px);
  font-weight: 600;
  letter-spacing: 0.14em;
  line-height: 1;
  padding: 0.4em 0.55em 0.34em;
  border-radius: 0.45em;
  background: color-mix(in srgb, currentColor 9%, transparent);
  color: color-mix(in srgb, currentColor 72%, transparent);
  align-self: center;
  transform: translateY(-0.06em);
}

/* ── BY RUN price column + filter bar (260711-0bg) — additive only ───────── */

/* Negative margin: converted cost exceeds converted price. Applied only
   when BOTH conversions exist — em-dash/plain cells carry no judgment.
   Price and Cost text stay neutral; the Margin figure carries the red. */
.margin-cell.is-loss,
.margin-cell.is-loss .money-figure {
  color: var(--color-bad);
}

/* Whole-row tint for the same judgment (row_class from table.capped_classed):
   subtle wash so the red price stays the loudest element in the row. */
.row-loss td {
  background: color-mix(in srgb, var(--color-bad) 7%, transparent);
}

.margin-filterbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
}

/* Child-owned spacing (no parent gap that could leak into .cost-section). */
.margin-filterbar > * {
  margin: 0 var(--space-4) var(--space-4) 0;
}

.margin-filter-select {
  width: auto;
}

.margin-filter-address {
  border: 1px solid var(--color-line);
  border-radius: var(--radius-2);
  background: var(--color-surface);
  color: var(--color-ink);
  font: 400 var(--text-sm) var(--font-sans);
  padding: var(--space-2) var(--space-3);
}

.margin-filter-address:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}

/* Double-range price slider: two overlaid native range inputs. The track is
   drawn once (on the container); each input contributes only its thumb. */
.price-slider-label {
  display: block;
  font: 400 var(--text-xs) var(--font-sans);
  color: var(--color-muted);
  margin-bottom: var(--space-2);
}

.price-slider-tracks {
  position: relative;
  width: 200px;
  height: 20px;
  border-radius: 999px;
}

.price-slider-tracks::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 4px;
  transform: translateY(-50%);
  border-radius: 999px;
  background: var(--color-line);
}

.price-slider-tracks input[type="range"] {
  position: absolute;
  inset: 0;
  width: 100%;
  margin: 0;
  -webkit-appearance: none;
  appearance: none;
  background: none;
  pointer-events: none;
}

.price-slider-tracks input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  pointer-events: auto;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid var(--color-line);
  background: var(--color-surface-raised);
  box-shadow: var(--shadow-soft);
  cursor: pointer;
}

.price-slider-tracks input[type="range"]::-moz-range-thumb {
  pointer-events: auto;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid var(--color-line);
  background: var(--color-surface-raised);
  box-shadow: var(--shadow-soft);
  cursor: pointer;
}

.price-slider-tracks input[type="range"]:focus {
  outline: none;
}

.price-slider-tracks input[type="range"]:focus::-webkit-slider-thumb {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}

.price-slider-tracks input[type="range"]:focus::-moz-range-thumb {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus);
}
