/*
 * HOIV Router: HOIV Chat's world (ui/chat/DESIGN.md) run as the router's dashboard. The tokens are
 * HOIV Chat's own, light and dark from the system. Orange is the primary action, focus, selection
 * and live state, and nothing else; red and amber mean a leg is failing or cooling. The dashboard's
 * older variable names stay as aliases of these, so every view keeps its rules.
 */
@font-face { font-family: 'Be Vietnam Pro'; font-style: normal; font-weight: 500; font-display: swap; src: url('fonts/be-vietnam-pro-latin-500-normal.woff2') format('woff2'); }
@font-face { font-family: 'Be Vietnam Pro'; font-style: normal; font-weight: 600; font-display: swap; src: url('fonts/be-vietnam-pro-latin-600-normal.woff2') format('woff2'); }
@font-face { font-family: 'Be Vietnam Pro'; font-style: normal; font-weight: 700; font-display: swap; src: url('fonts/be-vietnam-pro-latin-700-normal.woff2') format('woff2'); }
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400; font-display: swap; src: url('fonts/roboto-latin-400-normal.woff2') format('woff2'); }
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 500; font-display: swap; src: url('fonts/roboto-latin-500-normal.woff2') format('woff2'); }
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 700; font-display: swap; src: url('fonts/roboto-latin-700-normal.woff2') format('woff2'); }

:root {
  --c-bg: #ffffff;
  --c-panel: #f4f4f4;
  --c-raised: #ffffff;
  --c-bubble: #efefef;
  --c-hover: #e8e8e8;
  --c-line: #e2e2e2;
  --c-ink: #141414;
  --c-ink-2: #626262;
  --c-accent: #ff8a00;
  --c-accent-ink: #141414;
  --c-accent-soft: #fff1e0;
  --c-accent-text: #a35400;
  --c-focus: #141414;
  --c-danger: #b42318;
  --c-danger-soft: #fdecea;
  --c-warn: #8a5300;
  --c-warn-soft: #fff1e0;
  --c-scrim: rgb(20 20 20 / 0.42);
  --c-shadow: 0 1px 2px rgb(20 20 20 / 0.06), 0 8px 24px -6px rgb(20 20 20 / 0.14);
  --font-display: 'Be Vietnam Pro', ui-sans-serif, system-ui, sans-serif;
  --font-sans: 'Roboto', ui-sans-serif, system-ui, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);

  /* The dashboard's own names, as aliases. */
  --bg-color: var(--c-bg);
  --bg-surface: var(--c-raised);
  --bg-surface-hover: var(--c-hover);
  --text-primary: var(--c-ink);
  --text-secondary: var(--c-ink-2);
  --primary-color: var(--c-accent);
  --accent-color: var(--c-accent-text);
  --border-color: var(--c-line);
  --border-radius: 16px;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --c-bg: #121212;
    --c-panel: #181818;
    --c-raised: #1f1f1f;
    --c-bubble: #262626;
    --c-hover: #2c2c2c;
    --c-line: #333333;
    --c-ink: #f2f2f2;
    --c-ink-2: #a8a8a8;
    --c-accent-soft: #3a2608;
    --c-accent-text: #ffa53d;
    --c-focus: #ffffff;
    --c-danger: #ff9a8f;
    --c-danger-soft: #3a1714;
    --c-warn: #ffb44d;
    --c-warn-soft: #3a2608;
    --c-scrim: rgb(0 0 0 / 0.6);
    --c-shadow: 0 1px 2px rgb(0 0 0 / 0.4), 0 10px 28px -6px rgb(0 0 0 / 0.6);
    color-scheme: dark;
  }
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

[hidden] {
  display: none !important;
}

body {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.55;
  background-color: var(--c-bg);
  color: var(--c-ink);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

::selection {
  background: rgb(255 138 0 / 0.3);
  color: inherit;
}

:focus-visible {
  outline: 2px solid var(--c-focus);
  outline-offset: 2px;
}

input,
select,
textarea {
  caret-color: var(--c-accent-text);
}

::placeholder {
  color: var(--c-ink-2);
  opacity: 1;
}

* {
  scrollbar-width: thin;
  scrollbar-color: var(--c-line) transparent;
}

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

/* Icons are drawn, one stroke weight throughout, in the colour of their text. */
.icon {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── Signed out ─────────────────────────────────────────────────────────────── */

.signin-screen {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 40px 16px;
  background: var(--c-panel);
}

.signin-card {
  width: 100%;
  max-width: 400px;
  padding: 32px;
  background: var(--c-raised);
  border: 1px solid var(--c-line);
  border-radius: 24px;
  box-shadow: var(--c-shadow);
}

.signin-mark {
  display: block;
}

.signin-card h1 {
  margin-top: 24px;
  font-size: 26px;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

.signin-lead {
  margin: 8px 0 24px;
  color: var(--c-ink-2);
}

.signin-reason {
  margin: -8px 0 16px;
  font-size: 14px;
  color: var(--c-danger);
}

.token-signin {
  margin-top: 20px;
}

.token-signin > summary {
  width: fit-content;
  font-size: 13px;
  color: var(--c-ink-2);
  cursor: pointer;
  list-style: none;
}

.token-signin > summary::-webkit-details-marker {
  display: none;
}

.token-signin > summary:hover {
  color: var(--c-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.token-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}

.token-form input {
  width: 100%;
}

/* ── The shell ──────────────────────────────────────────────────────────────── */

.app-container {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  position: sticky;
  top: 0;
  flex: 0 0 260px;
  width: 260px;
  height: 100vh;
  padding: 16px 12px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  background-color: var(--c-panel);
  border-right: 1px solid var(--c-line);
}

.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 12px 2px;
}

.wordmark {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 12px;
  color: var(--c-ink);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  transition: background-color 0.15s;
}

.nav-item .icon {
  color: var(--c-ink-2);
}

.nav-item:hover {
  background-color: var(--c-hover);
}

.nav-item.active {
  background-color: var(--c-hover);
}

.nav-item.active .icon {
  color: var(--c-ink);
}

.sidebar-foot {
  margin-top: auto;
  padding-top: 12px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-top: 1px solid var(--c-line);
}

.account {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px 6px 12px;
}

.avatar {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border-radius: 999px;
  background: var(--c-bubble);
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
}

.avatar:empty {
  display: none;
}

.account-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-size: 14px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--c-ink-2);
  cursor: pointer;
}

.icon-btn:hover {
  background: var(--c-hover);
  color: var(--c-ink);
}

.content {
  flex: 1;
  min-width: 0;
  padding: 32px 40px 56px;
}

input[type='text'],
input[type='password'],
input[type='number'],
input[type='date'],
input[type='url'],
input[type='search'],
select,
textarea {
  padding: 9px 12px;
  border: 1px solid var(--c-line);
  border-radius: 12px;
  background-color: var(--c-bg);
  color: var(--c-ink);
  font: inherit;
  font-size: 14px;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--c-ink-2);
  box-shadow: 0 0 0 3px rgb(255 138 0 / 0.25);
}

.view {
  display: none;
  max-width: 1180px;
  margin: 0 auto;
}

.view.active {
  display: block;
  animation: rise-in 360ms var(--ease-out-expo) both;
}

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

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

.view-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 20px;
}

.view-header h1 {
  font-size: 26px;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

/* A header with a line under its title: the title and its action share the top line at every
   width, and the line runs beneath both. */
.view-header.has-sub {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  row-gap: 0;
}

.view-header.has-sub > div {
  display: contents;
}

.view-header.has-sub .view-sub {
  grid-column: 1 / -1;
  grid-row: 2;
}

.view-header.has-sub > .btn {
  grid-column: 2;
  grid-row: 1;
}

/* Buttons: pills, the primary one orange with dark text (white on #FF8A00 is 2.2:1). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 16px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s, border-color 0.15s, filter 0.15s;
}

.btn .icon {
  width: 16px;
  height: 16px;
}

.btn.primary {
  background: var(--c-accent);
  color: var(--c-accent-ink);
}

.btn.primary:hover {
  filter: brightness(0.95);
}

.btn.secondary {
  background-color: var(--c-raised);
  border-color: var(--c-line);
  color: var(--c-ink);
}

.btn.secondary:hover {
  background-color: var(--c-hover);
}

.btn.danger {
  background-color: transparent;
  border-color: var(--c-line);
  color: var(--c-danger);
}

.btn.danger:hover {
  background-color: var(--c-danger-soft);
  border-color: transparent;
}

.btn.danger-fill {
  background: var(--c-danger);
  color: var(--c-bg);
}

.btn.danger-fill:hover {
  filter: brightness(0.95);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn.block {
  width: 100%;
}

/* Cards and tables: one hairline card per table, no shadow; shadows are for what floats. */
.card {
  background-color: var(--c-raised);
  border: 1px solid var(--c-line);
  border-radius: var(--border-radius);
  overflow: hidden;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.data-table th,
.data-table td {
  padding: 12px 16px;
  text-align: left;
  border-bottom: 1px solid var(--c-line);
}

.data-table th {
  color: var(--c-ink-2);
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 600;
}

.data-table tr:last-child td {
  border-bottom: none;
}

.data-table tbody tr:hover > td {
  background-color: rgb(127 127 127 / 0.04);
}

.token-badge {
  padding: 2px 8px;
  border-radius: 8px;
  background-color: var(--c-bubble);
  color: var(--c-ink-2);
  font-family: var(--font-mono);
  font-size: 12px;
}

/* Modals */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  justify-content: center;
  align-items: center;
  padding: 16px;
  background-color: var(--c-scrim);
}

.modal-backdrop.active {
  display: flex;
}

.modal {
  width: 100%;
  max-width: 480px;
  max-height: 90vh;
  padding: 28px;
  overflow-y: auto;
  border-radius: 20px;
  box-shadow: var(--c-shadow);
}

.modal.confirm {
  max-width: 440px;
}

.confirm-body {
  margin-top: -8px;
  color: var(--c-ink-2);
  font-size: 14px;
  white-space: pre-line;
}

/* Modals carrying a table need room for every column; at 480px the trailing
   action cell was pushed outside the panel and became unclickable. */
.modal.wide {
  max-width: 720px;
}

.modal h2 {
  margin-bottom: 20px;
  font-size: 20px;
  letter-spacing: -0.01em;
}

/* A modal that scrolls as one block can put its Save button below the fold, which reads as a
   dialog with no way to commit. Where a body wrapper is present, only the body scrolls and the
   actions stay pinned in view. */
.modal:has(> .modal-body) {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.modal-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* Space so a focus ring on the last control is not clipped by the scroll container. */
  padding: 2px;
  margin: -2px;
}

.modal:has(> .modal-body) .modal-actions {
  flex: 0 0 auto;
  padding-top: 20px;
  border-top: 1px solid var(--c-line);
  margin-top: 20px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 18px;
}

.form-group label {
  color: var(--c-ink);
  font-size: 13px;
  font-weight: 500;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 28px;
}

/* Fixed, and above the modal backdrop. As an in-flow element it sat behind any open
   modal, so a rejected credential or a 400 from the admin API produced no visible
   feedback at all: the click just appeared to do nothing. */
.banner {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  max-width: min(720px, calc(100vw - 32px));
  padding: 10px 16px;
  border: 1px solid var(--c-line);
  border-radius: 14px;
  background: var(--c-raised);
  color: var(--c-ink);
  font-size: 14px;
  box-shadow: var(--c-shadow);
}

.banner.error {
  background: var(--c-danger-soft);
  border-color: transparent;
}

.banner.success {
  background: var(--c-raised);
}

.banner.info {
  background: var(--c-raised);
  color: var(--c-ink);
}

.hint {
  margin-top: 6px;
  color: var(--c-ink-2);
  font-size: 13px;
  line-height: 1.5;
}

.view-header + .hint {
  margin-bottom: 20px;
}

/* Stacked cards in a view keep apart, and so does a note between them. */
.view > .card + .card,
.view > .hint + .card,
.view > .card + .stats-grid,
.view > .stats-grid + .card {
  margin-top: 16px;
}

.form-row {
  display: flex;
  gap: 16px;
}

.form-row .form-group {
  flex: 1;
}

.form-row .form-group.narrow {
  flex: 0 0 96px;
}

.btn.btn-small {
  padding: 6px 12px;
  font-size: 13px;
}

.mono {
  font-family: var(--font-mono);
  font-size: 13px;
}

.muted {
  color: var(--c-ink-2);
}

.strong {
  font-weight: 500;
}

.small {
  font-size: 13px;
}

.empty {
  padding: 28px 16px;
  color: var(--c-ink-2);
  text-align: center;
}

/* Pills: sentence case, quiet, and coloured only when the colour says something. */
.pill {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--c-bubble);
  color: var(--c-ink);
  font-size: 12px;
  font-weight: 500;
  vertical-align: middle;
  white-space: nowrap;
}

/* A pill that is the whole cell carries no leading gap. */
td > .pill:first-child {
  margin-left: 0;
}

/* "Fine" needs no colour: a neutral chip. Amber says cooling or costly, red says failing. */
.pill.ok {
  background: var(--c-bubble);
  color: var(--c-ink);
}

.pill.warn {
  background: var(--c-warn-soft);
  color: var(--c-warn);
}

.pill.danger {
  background: var(--c-danger-soft);
  color: var(--c-danger);
}


/* Project cell: the name is the heading, the token and date are secondary identifiers. */
.key-title {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.key-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}

/* In a flex row the gap spaces the pills; a margin of their own would indent one that wraps. */
.key-title .pill,
.key-meta .pill {
  margin-left: 0;
}

/* Chains: a line per profile, its legs as pills in failover order, joined by a short rule. The
   lead leg is set in ink because it answers unless it fails; a failing one is marked in red. */
.chains {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.chain-of {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.chain-profile {
  flex: 0 0 78px;
  padding-top: 3px;
  overflow: hidden;
  color: var(--c-ink-2);
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.legs {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.leg {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border: 1px solid var(--c-line);
  border-radius: 999px;
  font-size: 12.5px;
  white-space: nowrap;
}

/* A short rule joins each leg to the next. A chain that wraps drops its rules (.wrapped, set by
   app.js), which would point at nothing from the end of a line; they keep their space. */
.leg:not(:last-child) {
  margin-right: 14px;
}

.leg:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -12px;
  width: 10px;
  height: 1px;
  background: var(--c-ink-2);
}

.legs.wrapped .leg::after {
  display: none;
}

/* The chain is what the keys table is read for: it takes the width the other columns leave. */
.data-table td.chain-cell {
  width: 100%;
}

.leg-provider {
  font-weight: 500;
}

.leg-model {
  color: var(--c-ink-2);
}

.leg-flag {
  padding: 0 6px;
  border-radius: 999px;
  background: var(--c-bubble);
  color: var(--c-ink-2);
  font-size: 11px;
}

.leg.lead {
  border-color: var(--c-ink);
  background: var(--c-ink);
  color: var(--c-bg);
}

.leg.lead .leg-model {
  color: inherit;
  opacity: 0.72;
}

.leg.lead .leg-flag {
  background: color-mix(in srgb, currentColor 16%, transparent);
  color: inherit;
}

.leg.failing {
  border-color: var(--c-danger);
  background: var(--c-danger-soft);
  color: var(--c-ink);
}

.leg.cooling {
  border-color: var(--c-warn);
  background: var(--c-warn-soft);
  color: var(--c-ink);
}

.leg.cooling .leg-model,
.leg.failing .leg-model {
  color: var(--c-ink-2);
  opacity: 1;
}

.leg.failing .leg-provider::before,
.leg.cooling .leg-provider::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 5px;
  border-radius: 999px;
  background: var(--c-danger);
  vertical-align: 1px;
}

.leg.cooling .leg-provider::before {
  background: var(--c-warn);
}


.chain-provider-name {
  color: var(--text-secondary);
}

/* ── Failover chain editor ─────────────────────────────────────────────────
   Rows are draggable cards rather than form lines: the order IS the setting, so it has to be
   the most visible thing about them and directly manipulable. */
/* No scroll of its own: .modal-body is the single scrolling region, and nesting a second one
   here produced two adjacent scrollbars for one list. */
.chain-editor {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}

/* A labelled break, so a section heading is not mistaken for the end of the hint above it. */
.form-group.section {
  border-top: 1px solid var(--border-color);
  padding-top: 20px;
  margin-top: 24px;
}

.form-group.section > label {
  color: var(--text-primary);
  font-size: 1rem;
}

.chain-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 10px 12px;
  background: var(--bg-color);
  border: 1px solid var(--border-color);
  border-radius: 12px;
}

/* The leg that answers unless it fails: its number is set in ink, the rest follow in grey. */
.chain-row:first-child .chain-index {
  color: var(--c-bg);
  background: var(--c-ink);
  border-radius: 999px;
  font-weight: 700;
}

.chain-row.dragging {
  opacity: 0.5;
  border-style: dashed;
}

.chain-grip {
  cursor: grab;
  color: var(--text-secondary);
  font-size: 1rem;
  line-height: 1.6;
  user-select: none;
  flex: 0 0 auto;
}

.chain-grip:active { cursor: grabbing; }

.chain-grip .icon,
.chain-remove .icon {
  width: 16px;
  height: 16px;
}

.chain-index {
  flex: 0 0 22px;
  height: 22px;
  margin-top: 4px;
  text-align: center;
  color: var(--text-secondary);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  line-height: 22px;
}

.chain-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.chain-line {
  display: flex;
  gap: 8px;
  align-items: center;
}

.chain-line select,
.chain-line input[type='text'] {
  min-width: 0;
}

.chain-provider { flex: 0 0 34%; }

.chain-model-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  gap: 6px;
  align-items: center;
}

.chain-model { flex: 1; min-width: 0; }
.chain-line-sub { font-size: 0.8125rem; }
.chain-role { flex: 0 0 5.5rem; }
.chain-effort { flex: 0 0 auto; }
.chain-allowed { flex: 1; font-size: 0.8125rem; }
.chain-remove { flex: 0 0 auto; }

.chain-add {
  display: flex;
  gap: 8px;
  align-items: center;
}

.chain-add select { flex: 0 0 34%; }

.chain-hint { margin-bottom: 10px; }

.model-source {
  flex: 0 0 auto;
  font-size: 0.6875rem;
}

.pill.muted-pill {
  background: var(--c-bubble);
  color: var(--c-ink-2);
}

.route-index {
  color: var(--text-secondary);
  font-size: 0.8125rem;
  width: 20px;
  flex: 0 0 20px;
}

.strict-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-secondary);
  font-size: 0.8125rem;
  cursor: pointer;
  user-select: none;
  flex: 0 0 auto;
}

.strict-toggle input {
  accent-color: var(--c-accent);
  cursor: pointer;
}

.data-table.compact th,
.data-table.compact td {
  padding: 10px 12px;
  font-size: 0.875rem;
}


/* ── Usage view ─────────────────────────────────────────────────────────────── */

.header-controls {
  display: flex;
  gap: 12px;
  align-items: center;
}

/* A card's own heading, a level under the view's title. Scoped to views: a dialog's title is an h2
   in a card too, and keeps its own size. */
.view .card h2 {
  font-size: 15px;
  font-weight: 600;
  padding: 20px 24px 0;
  margin: 0;
}

.view .card h2 + .hint {
  padding: 0 24px;
  margin-top: 4px;
}

.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin-bottom: 24px;
  border: 1px solid var(--c-line);
  border-radius: var(--border-radius);
  background: var(--c-raised);
  overflow: hidden;
}

.stat {
  padding: 18px 20px;
  border-left: 1px solid var(--c-line);
}

.stat:first-child {
  border-left: none;
}

.stat-value {
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.2;
  /* Tabular figures stop the numbers jittering as they refresh. */
  font-variant-numeric: tabular-nums;
}

.stat-label {
  color: var(--text-secondary);
  font-size: 0.8125rem;
  margin-top: 4px;
}

.stat-sub {
  color: var(--text-secondary);
  font-size: 0.75rem;
  margin-top: 8px;
  opacity: 0.75;
}

.chart-card {
  margin-bottom: 24px;
  padding-bottom: 20px;
}

.chart {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 3px;
  height: 160px;
  padding: 20px 24px 0;
  overflow-x: auto;
}

.bar-column {
  flex: 1 1 0;
  min-width: 6px;
  max-width: 48px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  gap: 6px;
}

.bar-stack {
  width: 100%;
  min-height: 2px;
  background: var(--c-ink-2);
  border-radius: 3px 3px 0 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

/* A day without requests keeps its place on the baseline, so the gap is visible. */
.bar-stack.quiet {
  height: 2px;
  min-height: 2px;
  background: var(--c-bubble);
}

/* Failures sit at the top of each bar so a bad day is visible at a glance, as a red-edged wash:
   this view is about cost, and solid red belongs to a leg failing now. */
.bar-errors {
  width: 100%;
  background-color: var(--c-danger-soft);
  box-shadow: inset 0 0 0 1px var(--c-danger);
  border-radius: 3px 3px 0 0;
}

/* Only some days are labelled; the rest keep the label's height so every bar shares a baseline. */
.bar-label {
  height: 14px;
  color: var(--text-secondary);
  font-size: 0.6875rem;
  line-height: 14px;
  white-space: nowrap;
}

.data-table th.num,
.data-table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.danger-text {
  color: var(--c-danger);
}

.chart .empty {
  align-self: center;
  margin: auto;
}

/* ── Responsive ──────────────────────────────────────────────────────────────
   The dashboard shipped with a fixed 260px sidebar and no media queries, so in a
   narrow window the navigation ate half the viewport and the tables pushed the page
   into sideways scrolling. */

/* Tables are the widest thing here; let them scroll inside their own card rather than
   dragging the whole page sideways. */
.card {
  overflow-x: auto;
}

.data-table {
  min-width: 520px;
}

@media (max-width: 900px) {
  .app-container {
    flex-direction: column;
  }

  /* On a narrow screen the sidebar becomes a top bar: the logo, the views across, the account. */
  .sidebar {
    flex: 0 0 auto;
    width: 100%;
    height: auto;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    padding: 10px 16px;
    border-right: none;
    border-bottom: 1px solid var(--c-line);
    z-index: 50;
  }

  .logo {
    padding: 0;
  }

  /* The base rule stacks nav vertically; in a top bar it has to run across. */
  .sidebar nav {
    order: 3;
    flex: 1 0 100%;
    flex-direction: row;
    gap: 2px;
    overflow-x: auto;
  }

  .sidebar .nav-item {
    white-space: nowrap;
    padding: 7px 10px;
  }

  .sidebar-foot {
    order: 2;
    margin: 0 0 0 auto;
    padding: 0;
    flex-direction: row;
    align-items: center;
    border-top: none;
  }

  .sidebar-foot .account-name {
    display: none;
  }

  .account {
    padding: 0;
  }

  .content {
    padding: 12px 16px 40px;
  }

  .view-header {
    flex-wrap: wrap;
    gap: 12px;
  }

  .view-header h1 {
    font-size: 1.5rem;
  }

  .stat-row {
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 12px;
  }

  .stat {
    padding: 16px;
  }

  .stat-value {
    font-size: 1.375rem;
  }

  .modal {
    padding: 24px 20px;
  }

  /* Stacking these keeps the inputs usable instead of crushing three onto one line. */
  .form-row {
    flex-direction: column;
    gap: 0;
  }

  .form-row .form-group.narrow {
    flex: 1;
  }

  .route-row {
    flex-wrap: wrap;
  }

  .route-row select,
  .route-row input[type='text'] {
    flex: 1 1 100%;
  }
}

/* Action cells hold two buttons now (Edit/Delete, Suspend/Revoke, Park/Remove). */
/* Not display:flex on the cell itself — that takes the <td> out of the table's row layout, so
   the buttons stopped lining up with the row they belong to once rows grew taller. */
.data-table td.actions {
  white-space: nowrap;
  width: 1%;
}

.data-table td.actions > * + * {
  margin-left: 6px;
}

/* A key's row is as tall as its chains: its name and actions sit at the top, beside the first. */
#keys-view .data-table td {
  vertical-align: top;
}

/* In the keys table the actions stack, so the chains beside them keep a line each. */
#keys-view .data-table td.actions > * {
  display: flex;
  width: 100%;
  margin: 0 0 6px;
}

/* A suspended key or parked credential is still a real row — dim it, don't hide it. */
.row-parked td:not(.actions) {
  opacity: 0.55;
}

/* Long absolute paths otherwise set the table's width on their own. */
.data-table td.truncate {
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 900px) {
  .data-table td.truncate {
    max-width: 180px;
  }
}

/* The advanced provider fields matter for a non-Claude CLI but would swamp the common case. */
.advanced {
  border-top: 1px solid var(--border-color);
  margin-top: 8px;
  padding-top: 16px;
}

.advanced > summary {
  cursor: pointer;
  color: var(--text-secondary);
  font-size: 0.875rem;
  font-weight: 500;
  margin-bottom: 16px;
  user-select: none;
}

.advanced > summary:hover {
  color: var(--text-primary);
}

.hint code {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  background: var(--c-bubble);
  padding: 1px 5px;
  border-radius: 4px;
}

/* ── Connection probe ───────────────────────────────────────────────────────── */

.probe-status {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 16px;
}

.probe-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border-color);
}

.probe-row:last-child {
  border-bottom: none;
}

.probe-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 8px;
  background: var(--text-secondary);
}

.probe-dot.ok { background: var(--c-ink-2); }
.probe-dot.bad { background: var(--c-danger); }
.probe-dot.warn { background: var(--c-warn); }
.probe-dot.info { background: var(--text-secondary); }

.probe-label {
  flex: 0 0 130px;
  font-size: 0.875rem;
  font-weight: 500;
}

.probe-detail {
  font-size: 0.8125rem;
  /* A CLI error can be long; wrap it rather than pushing the panel wider. */
  overflow-wrap: anywhere;
}

.probe-hint {
  position: static;
  transform: none;
  max-width: none;
  box-shadow: none;
  margin-top: 12px;
}

@media (max-width: 900px) {
  .probe-row { flex-wrap: wrap; }
  .probe-label { flex-basis: auto; }
}

/* ── Auto-discovery ─────────────────────────────────────────────────────────── */

.discover-item {
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius);
  padding: 16px;
  margin-bottom: 12px;
}

/* A CLI that is not installed is still worth listing, just visibly secondary. */
.discover-item.missing {
  opacity: 0.55;
}

.discover-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 6px;
}

.discover-path {
  overflow-wrap: anywhere;
}

.discover-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

/* Model chips in the discovery card: neutral = the CLI reported it, amber = our own list, to verify
   by probing. */
.model-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.model-chips .pill {
  margin-left: 0;
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--font-mono);
}

/* ── CLI login panel ─────────────────────────────────────────────────────────
   Shown where "no credentials" used to be the whole story: these providers do have
   a login, it expires, and the router cannot renew it. */
.auth-panel {
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius);
  padding: 14px 16px;
  margin-bottom: 20px;
}

.auth-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}

.auth-label {
  flex: 0 0 54px;
  color: var(--text-secondary);
  font-size: 0.8125rem;
}

.auth-path {
  overflow-wrap: anywhere;
  flex: 1 1 220px;
}

.auth-cmd {
  flex: 1 1 100%;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  background: var(--bg-color);
  border: 1px solid var(--border-color);
  border-radius: 6px;
  padding: 8px 10px;
  overflow-wrap: anywhere;
  user-select: all;
}

.auth-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 4px;
}

/* ── Stats ────────────────────────────────────────────────────────────────────
   Activity is drawn in one ordinal ramp of grey to ink, light to strong on the light theme and
   dark to light on the dark one, so the busiest cell is always the one that stands out. Orange
   stays for actions and live state. The punchcard uses the same ramp: both measure the same
   thing, calls. Token kinds keep their four categorical slots, which carry direct labels:
     token kinds        #3987e5 #d95926 #199e70 #c98500 */
:root {
  --heat-empty: #efefef;
  --heat-1: #cfcfcf;
  --heat-2: #9a9a9a;
  --heat-3: #5f5f5f;
  --heat-4: #1f1f1f;
}
@media (prefers-color-scheme: dark) {
  :root {
    --heat-empty: #262626;
    --heat-1: #474747;
    --heat-2: #767676;
    --heat-3: #ababab;
    --heat-4: #ececec;
  }
}
.stats-body {
  --hm-cell: 14px;
  --hm-dot: 11px;
  transition: opacity 0.15s ease;
}
.stats-body.is-loading {
  opacity: 0.5;
}
.view-sub {
  color: var(--text-secondary);
  font-size: 0.875rem;
  margin: 4px 0 0;
}

.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: 10px;
}
#stats-view .view-header {
  flex-wrap: wrap;
  gap: 16px;
}
.segmented button {
  white-space: nowrap;
  background: transparent;
  border: 0;
  border-radius: 7px;
  color: var(--text-secondary);
  cursor: pointer;
  font: inherit;
  font-size: 0.8125rem;
  padding: 6px 12px;
}
.segmented button:hover {
  color: var(--text-primary);
}
.segmented button[aria-checked='true'] {
  background: var(--bg-surface-hover);
  color: var(--text-primary);
}
.segmented button:focus-visible,
.rank-row:focus-visible,
.heatmap:focus-visible,
.punchcard:focus-visible {
  outline: 2px solid var(--c-focus);
  outline-offset: 2px;
}

/* Seven tiles: narrower columns keep them on one row at a laptop's width, not six and an orphan. */
#statsTiles {
  grid-template-columns: repeat(auto-fit, minmax(124px, 1fr));
}

.viz-card {
  margin-bottom: 24px;
  padding-bottom: 20px;
}
.viz-head {
  align-items: flex-end;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: space-between;
  padding-right: 24px;
}
.viz-note {
  color: var(--text-secondary);
  font-size: 0.8125rem;
  margin: 0;
  padding: 8px 24px 0;
}

/* Heat grids: the wrapper is the hit target, so the gap between dots counts as the cell. */
/* No left padding: the sticky label column supplies the gutter itself, so nothing that scrolls
   under it can show through beside it. */
.heat-scroll {
  overflow-x: auto;
  padding: 16px 24px 4px 0;
  scrollbar-color: var(--c-line) transparent;
  scrollbar-width: thin;
}
.heatmap {
  display: inline-grid;
  grid-template-columns: auto auto;
  column-gap: 8px;
  border-radius: 6px;
  outline: none;
}
.hm-months {
  color: var(--text-secondary);
  display: grid;
  font-size: 0.6875rem;
  height: 18px;
}
/* The weekday column stays put while the weeks scroll under it, as on GitHub. */
.hm-corner,
.hm-days {
  background: var(--bg-surface);
  left: 0;
  position: sticky;
  z-index: 1;
}
.hm-corner,
.hm-days,
.pc-day {
  padding-left: 24px;
}
.hm-days {
  padding-right: 6px;
  align-items: center;
  color: var(--text-secondary);
  display: grid;
  font-size: 0.6875rem;
  grid-template-rows: repeat(7, var(--hm-cell));
}
.hm-grid {
  display: grid;
  grid-auto-columns: var(--hm-cell);
  grid-auto-flow: column;
  grid-template-rows: repeat(7, var(--hm-cell));
}
.hm-cell,
.pc-cell {
  align-items: center;
  display: flex;
  justify-content: center;
}
.hm-dot {
  border-radius: 2px;
  display: inline-block;
  height: var(--hm-dot);
  width: var(--hm-dot);
}
.hm-cell.is-selected .hm-dot,
.pc-cell.is-selected .pc-dot {
  box-shadow:
    0 0 0 2px var(--bg-surface),
    0 0 0 3px var(--text-primary);
}
.lv-0,
.pv-0 {
  background: var(--heat-empty);
}
.lv-1 { background: var(--heat-1); }
.lv-2 { background: var(--heat-2); }
.lv-3 { background: var(--heat-3); }
.lv-4 { background: var(--heat-4); }
/* Before the ledger existed: unknown, drawn as an outline so it never reads as a quiet day. */
.lv-x {
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--c-line);
}
.pv-1 { background: var(--heat-1); }
.pv-2 { background: var(--heat-2); }
.pv-3 { background: var(--heat-3); }
.pv-4 { background: var(--heat-4); }

.heat-legend {
  align-items: center;
  color: var(--text-secondary);
  display: flex;
  flex-wrap: wrap;
  font-size: 0.75rem;
  gap: 4px;
}
.heat-legend .hm-dot {
  height: 10px;
  width: 10px;
}
.legend-extra {
  align-items: center;
  display: inline-flex;
  gap: 4px;
  margin-left: 12px;
}

.punchcard {
  align-items: center;
  border-radius: 6px;
  display: inline-grid;
  grid-auto-rows: 22px;
  grid-template-columns: auto repeat(24, 22px);
  outline: none;
}
.pc-hour {
  color: var(--text-secondary);
  font-size: 0.6875rem;
}
.pc-day {
  background: var(--bg-surface);
  color: var(--text-secondary);
  font-size: 0.6875rem;
  left: 0;
  padding-right: 8px;
  position: sticky;
  z-index: 1;
  align-self: stretch;
  display: flex;
  align-items: center;
}
.pc-cell {
  height: 22px;
  width: 22px;
}
.pc-dot {
  border-radius: 3px;
  display: inline-block;
  height: 18px;
  width: 18px;
}

.stats-grid {
  display: grid;
  gap: 0 24px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 960px) {
  .stats-grid {
    grid-template-columns: 1fr;
  }
}

/* Rankings: one series, so one colour; thin bars, a rounded data end, square at the baseline. */
.rank-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 24px 0;
}
.rank-row {
  border-radius: 8px;
  margin: 0 -8px;
  outline: none;
  padding: 8px;
}
.rank-row:hover,
.rank-row:focus-visible {
  background: var(--bg-surface-hover);
}
.rank-head {
  align-items: flex-start;
  display: flex;
  gap: 12px;
  min-width: 0;
}
.rank-label {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
/* break-word, not anywhere: a name breaks only when it cannot fit at all, never as "opu / s". */
.rank-name {
  font-size: 0.875rem;
  overflow-wrap: break-word;
}
.rank-sub {
  color: var(--text-secondary);
  font-size: 0.75rem;
}
.rank-value {
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  margin-left: auto;
  white-space: nowrap;
}
.rank-track {
  height: 8px;
  margin-top: 6px;
}
.rank-fill {
  background: var(--c-ink-2);
  border-radius: 0 4px 4px 0;
  height: 100%;
}
.rank-row.is-other .rank-fill {
  background: var(--c-ink-2);
  opacity: 0.45;
}

/* Token breakdown: part-to-whole, 2px surface gaps between segments, no strokes. */
.tk-bar {
  display: flex;
  gap: 2px;
  height: 16px;
  margin: 16px 24px 0;
}
.tk-seg {
  flex-basis: 3px;
  flex-shrink: 0;
  min-width: 3px;
}
.tk-seg:first-child {
  border-radius: 4px 0 0 4px;
}
.tk-seg:last-child {
  border-radius: 0 4px 4px 0;
}
.tk-seg:only-child {
  border-radius: 4px;
}
.tk-1 { background: #3987e5; }
.tk-2 { background: #d95926; }
.tk-3 { background: #199e70; }
.tk-4 { background: #c98500; }
.tk-legend {
  display: grid;
  gap: 8px;
  list-style: none;
  margin: 16px 24px 0;
  padding: 0;
}
.tk-legend li {
  align-items: center;
  display: grid;
  font-size: 0.875rem;
  gap: 10px;
  grid-template-columns: 12px 1fr auto auto;
}
.tk-swatch {
  border-radius: 3px;
  height: 12px;
  width: 12px;
}
.tk-value,
.tk-share {
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.tk-share {
  color: var(--text-secondary);
  min-width: 3.5em;
}

/* Table twins: every value is reachable without hovering. */
.table-twin {
  font-size: 0.8125rem;
  margin: 12px 24px 0;
}
.table-twin summary {
  color: var(--text-secondary);
  cursor: pointer;
}
.table-twin > div {
  margin-top: 8px;
  max-height: 320px;
  overflow: auto;
}
.table-twin .data-table th,
.table-twin .data-table td {
  padding: 6px 10px;
}
.table-twin .num {
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.viz-tooltip {
  background: var(--c-raised);
  color: var(--c-ink);
  border: 1px solid var(--c-line);
  border-radius: 12px;
  box-shadow: var(--c-shadow);
  max-width: 300px;
  padding: 8px 10px;
  pointer-events: none;
  position: fixed;
  z-index: 1000;
}
.tip-value {
  color: var(--text-primary);
  font-weight: 700;
}
.tip-label {
  color: var(--text-secondary);
  font-size: 0.8125rem;
}
.tip-sub {
  color: var(--text-secondary);
  font-size: 0.75rem;
  margin-top: 2px;
}

/* ── Failing legs ──────────────────────────────────────────────────────────── */

/* Pinned while a routed leg is failing. In flow rather than fixed like .banner: this is a
   standing fact, not a notification, and it must not cover anything. */
.leg-alerts {
  display: grid;
  gap: 8px;
  margin-bottom: 16px;
}

/* display:grid above would otherwise beat the UA stylesheet's [hidden] rule. */
.leg-alerts[hidden] {
  display: none;
}

.leg-alert {
  padding: 12px 16px;
  border-radius: 14px;
  font-size: 0.875rem;
  background: var(--c-danger-soft);
  color: var(--c-ink);
}

/* ── People ──────────────────────────────────────────────────────────────────── */

.people-table td {
  vertical-align: top;
}

.profile-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-width: 280px;
}

.profile-list .pill {
  margin-left: 0;
  text-transform: none;
  letter-spacing: 0;
}

.until-line {
  margin-top: 8px;
}

.until-line .pill,
.key-title .pill.muted-pill {
  text-transform: none;
  letter-spacing: 0;
}

.until-line .pill {
  margin-left: 0;
}

/* What a person has used of each ceiling today: a figure, then a bar that turns at 90%. */
.allowance-cell {
  min-width: 190px;
}

.allowance + .allowance,
.allowance + .muted {
  margin-top: 10px;
}

.allowance-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  font-size: 0.8125rem;
}

.allowance-figure {
  font-variant-numeric: tabular-nums;
}

.allowance-free {
  font-size: 0.8125rem;
}

.cooldown-state {
  display: flex;
  align-items: center;
  gap: 8px;
}

.cooldown-state .pill {
  margin-left: 0;
}

.meter {
  height: 4px;
  margin-top: 4px;
  border-radius: 999px;
  background: var(--c-bubble);
  overflow: hidden;
}

.meter > span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--c-accent);
}

.meter.hot > span {
  background: var(--c-danger);
}

/* A person's actions in two columns: what to change on top, whether they keep access below. */
.people-table td.actions {
  width: 1%;
}

.action-wrap {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
  min-width: 250px;
}

.people-table .action-wrap {
  display: grid;
  grid-template-columns: repeat(2, max-content);
  justify-content: end;
  min-width: 0;
}

.profile-picks {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.profile-pick {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 1px solid var(--border-color);
  border-radius: 999px;
  background: var(--bg-color);
  font-size: 0.875rem;
  cursor: pointer;
  user-select: none;
}

.profile-pick:has(input:checked) {
  border-color: var(--c-ink);
}

.profile-pick input {
  accent-color: var(--c-accent);
  cursor: pointer;
}

.until-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.until-picks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.token-reveal {
  display: flex;
  gap: 8px;
  margin: 16px 0;
}

.token-reveal input {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
}

/* A leg's profile in the chain editor: which named chain it belongs to. The same class labels a
   chain in the keys table, so this stays inside the editor. */
.chain-editor .chain-profile {
  flex: 0 0 6.5rem;
  font-size: 0.8125rem;
  padding: 6px 10px;
}

.chain-profile-tag {
  flex: 0 0 auto;
  color: var(--text-secondary);
  font-size: 0.75rem;
  min-width: 4.5rem;
}

/* Four ceilings side by side do not fit a dialog; two by two do, and one column on a phone. */
.limits-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  column-gap: 16px;
}

.limits-grid input {
  width: 100%;
}

/* ── Card insets ─────────────────────────────────────────────────────────────
   A card's content never touches its border. A table sits 8px in from every edge, and its outer
   cells pad 16px instead of 24px, so the text lands on the same 24px line as the card's heading
   and the columns between keep their spacing. Dialogs are cards too, but pad 28px themselves. */
.card:not(.modal) > .data-table {
  width: calc(100% - 16px);
  margin: 8px;
}

.card:not(.modal) > .data-table th:first-child,
.card:not(.modal) > .data-table td:first-child {
  padding-left: 16px;
}

.card:not(.modal) > .data-table th:last-child,
.card:not(.modal) > .data-table td:last-child {
  padding-right: 16px;
}

/* What a script fills into a card (plan costs, unreachable budgets) sits on the same 24px line as
   the card's heading and tables. It used to have no inset at all and ran into the border. */
.card-body {
  padding: 4px 24px 16px;
}

/* A card that is all body has no heading to space it from the top. */
.card.card-body {
  padding-top: 12px;
}

/* On a phone a table scrolls inside its card rather than being cut off by it; the keys and the
   people, read most, stack instead: name, then chains or access, then the actions. */
@media (max-width: 700px) {
  .card {
    overflow-x: auto;
  }

  #keys-view .data-table thead,
  #people-view .data-table thead {
    display: none;
  }

  /* As blocks all the way down, so a row is as wide as the card and its legs wrap inside it. The
     520px floor the other tables keep, to scroll rather than squash, does not apply to these. */
  #keys-view .data-table,
  #keys-view .data-table tbody,
  #people-view .data-table,
  #people-view .data-table tbody {
    display: block;
    width: 100%;
    min-width: 0;
  }

  #keys-view .data-table tr,
  #people-view .data-table tr {
    display: block;
    padding: 10px 0;
    border-bottom: 1px solid var(--c-line);
  }

  #keys-view .data-table tr:last-child,
  #people-view .data-table tr:last-child {
    border-bottom: none;
  }

  #keys-view .data-table td,
  #people-view .data-table td {
    display: block;
    width: auto;
    padding: 6px 16px;
    border-bottom: none;
  }

  #keys-view .data-table td.actions > * {
    display: inline-flex;
    width: auto;
    margin: 0 6px 0 0;
  }

  /* Health is the view an alert on a phone opens. Each leg reads as its name and state, then what
     it last did, labelled, instead of four squeezed columns. */
  #health-view .data-table thead {
    display: none;
  }

  #health-view .data-table,
  #health-view .data-table tbody {
    display: block;
    width: 100%;
    min-width: 0;
  }

  #health-view .data-table tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--c-line);
  }

  #health-view .data-table tr:last-child {
    border-bottom: none;
  }

  #health-view .data-table td {
    display: block;
    padding: 0;
    border-bottom: none;
  }

  #health-view .data-table td.wide,
  #health-view .data-table td.lead,
  #health-view .data-table td.empty {
    flex-basis: 100%;
  }

  #health-view .data-table td.lead {
    order: -1;
  }

  #health-view .data-table td[data-label]::before {
    content: attr(data-label);
    margin-right: 6px;
    color: var(--c-ink);
    font-weight: 500;
  }

  .legs {
    flex-wrap: wrap;
  }
}

/* Below a laptop's width a chain gets the card's whole width: the profile above its legs, and no
   joining rule, which would dangle wherever a line wraps. The sliding view strip fades at its
   edge, so the views past it can be found. */
@media (max-width: 900px) {
  .chain-of {
    flex-direction: column;
    gap: 4px;
  }

  .chain-profile {
    flex: none;
    padding-top: 0;
  }

  .leg:not(:last-child) {
    margin-right: 6px;
  }

  .leg:not(:last-child)::after {
    display: none;
  }

  .sidebar nav {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
    padding-right: 24px;
  }
}
