/* ==========================================================================
   Components — one block per primitive in src/components/. Tokens only.
   Order: text → controls → status → surfaces → feedback → data → overlays.
   Responsive rules measure the content area (@container main), never the
   viewport.
   ========================================================================== */

/* ── Label ────────────────────────────────────────────────────────────── */
/* A small sentence-case label above a value or a group of controls. */
.ui-label {
  display: block;
  color: var(--text-dim);
  font-size: var(--text-12);
  font-weight: var(--weight-medium);
  line-height: var(--leading-snug);
}

/* ── Link: inline, in text or a value ─────────────────────────────────── */
.ui-link {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--duration-fast) var(--ease-out);
}

.ui-link:hover {
  text-decoration-color: currentColor;
}

/* ── Button ───────────────────────────────────────────────────────────── */
/* `ui-button` + one variant (primary | secondary | ghost | danger |
   danger-outline) + optional size (sm | lg) and `icon` for icon-only. */
.ui-button {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--control-md);
  padding: 0 var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-size: var(--text-13);
  font-weight: var(--weight-medium);
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.ui-button svg {
  flex: none;
}

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

.ui-button--sm {
  height: var(--control-sm);
  padding: 0 var(--space-3);
}

.ui-button--lg {
  height: var(--control-lg);
  padding: 0 var(--space-5);
  font-size: var(--text-14);
}

.ui-button--icon {
  width: var(--control-md);
  padding: 0;
}

.ui-button--icon.ui-button--sm {
  width: var(--control-sm);
}

.ui-button--primary {
  background: var(--accent);
  color: var(--accent-fg);
}

.ui-button--primary:not(:disabled):hover {
  background: var(--accent-hover);
}

.ui-button--secondary {
  border-color: var(--line-strong);
  background: var(--bg-raised);
  color: var(--text);
}

.ui-button--secondary:not(:disabled):hover {
  background: var(--bg-hover);
}

.ui-button--ghost {
  background: transparent;
  color: var(--text-dim);
}

.ui-button--ghost:not(:disabled):hover {
  background: var(--bg-hover);
  color: var(--text);
}

.ui-button--danger {
  background: var(--danger);
  color: var(--danger-fg);
}

.ui-button--danger:not(:disabled):hover {
  background: color-mix(in srgb, var(--danger) 88%, var(--text));
}

/* Destructive action in a list: quiet until hovered. */
.ui-button--danger-outline {
  border-color: var(--line-strong);
  background: transparent;
  color: var(--danger);
}

.ui-button--danger-outline:not(:disabled):hover {
  border-color: var(--danger-line);
  background: var(--danger-soft);
}

/* A row of actions; wraps before it overflows. */
.ui-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

/* ── Field ────────────────────────────────────────────────────────────── */
/* <label class="ui-field"><span class="ui-field__label">…</span><input>
   <span class="ui-field__hint">…</span></label> */
/* `.ui-editor-field` lays out a ScriptEditor or RichTextEditor like a field,
   without `.ui-field`'s input rules restyling it. */
.ui-field,
.ui-editor-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.ui-field__label {
  color: var(--text);
  font-size: var(--text-13);
  font-weight: var(--weight-medium);
  line-height: var(--leading-snug);
}

.ui-field__hint {
  color: var(--text-dim);
  font-size: var(--text-12);
  line-height: var(--leading-snug);
}

.ui-field__error {
  color: var(--danger);
  font-size: var(--text-12);
  line-height: var(--leading-snug);
}

.ui-field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--space-4);
}
.ui-field-grid > .ui-field--wide { grid-column: 1 / -1; }

/* ── Input / textarea ─────────────────────────────────────────────────── */
/* Bare inputs inside a field are styled as `ui-input` so page markup stays
   plain; standalone inputs take the class. */
.ui-input,
.ui-field :is(input:not([type="checkbox"], [type="radio"]), textarea) {
  width: 100%;
  min-width: 0;
  height: var(--control-md);
  padding: 0 var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: var(--text-13);
  transition: border-color var(--duration-fast) var(--ease-out);
}

/* An ID, address or token typed into a field reads in mono, like it prints. */
.ui-field :is(input, textarea).u-mono,
.ui-input.u-mono {
  font-family: var(--font-mono);
}

.ui-field textarea,
textarea.ui-input {
  height: auto;
  min-height: calc(var(--control-md) * 2);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-12);
  line-height: var(--leading-normal);
  resize: vertical;
}

.ui-input::placeholder,
.ui-field ::placeholder {
  color: var(--text-faint);
}

.ui-input:hover,
.ui-field :is(input, textarea):hover {
  border-color: var(--text-faint);
}

.ui-input:focus,
.ui-field :is(input, textarea):focus {
  border-color: var(--focus);
  outline: none;
  box-shadow: var(--focus-ring);
}

.ui-input[aria-invalid="true"],
.ui-field [aria-invalid="true"] {
  border-color: var(--danger);
}

.ui-input:disabled,
.ui-field :is(input, textarea):disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* An input with its unit after the value: <div class="ui-input-affix">
   <input>…<span class="ui-input-affix__suffix">GiB</span></div>. */
.ui-input-affix {
  position: relative;
  min-width: 0;
}

/* As specific as `.ui-field input`, and later, so the room for the unit holds. */
.ui-input-affix > input,
.ui-field .ui-input-affix > input {
  padding-right: calc(var(--space-3) + var(--affix-width, 4.5ch));
}

.ui-input-affix__suffix {
  position: absolute;
  top: 50%;
  right: var(--space-3);
  color: var(--text-faint);
  font-size: var(--text-12);
  pointer-events: none;
  transform: translateY(-50%);
}

/* ── Checkbox ─────────────────────────────────────────────────────────── */
.ui-checks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
}

.ui-check {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--control-sm);
  color: var(--text);
  font-size: var(--text-13);
  cursor: pointer;
}

.ui-check input {
  flex: none;
  width: var(--icon-md);
  height: var(--icon-md);
  margin: 0;
  accent-color: var(--accent);
}

/* A checkbox's hint reads under its words, not under the box. */
.ui-check + .ui-field__hint {
  margin-top: calc(-1 * var(--space-1));
  padding-left: calc(var(--icon-md) + var(--space-2));
}

/* ── Switch: <button class="ui-switch" role="switch" aria-checked> ───── */
.ui-switch {
  position: relative;
  flex: none;
  width: 32px;
  height: 18px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
}

.ui-switch:hover {
  border-color: var(--text-faint);
}

.ui-switch:focus-visible {
  outline: none;
  border-color: var(--focus);
  box-shadow: var(--focus-ring);
}

.ui-switch[aria-checked="true"] {
  border-color: var(--accent);
  background: var(--accent);
}

.ui-switch__thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 12px;
  height: 12px;
  border-radius: var(--radius-full);
  background: var(--text-dim);
  transition: transform var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out);
}

.ui-switch[aria-checked="true"] .ui-switch__thumb {
  background: var(--accent-fg);
  transform: translateX(14px);
}

.ui-switch-field {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--control-sm);
  color: var(--text);
  font-size: var(--text-13);
  cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
  .ui-switch, .ui-switch__thumb { transition: none; }
}

/* ── Select ───────────────────────────────────────────────────────────── */
.ui-select {
  position: relative;
  min-width: 0;
}

.ui-select__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  height: var(--control-md);
  padding: 0 var(--space-2) 0 var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--bg);
  color: var(--text);
  font-size: var(--text-13);
  text-align: left;
  transition: border-color var(--duration-fast) var(--ease-out);
}

.ui-select__trigger:not(:disabled):hover {
  border-color: var(--text-faint);
}

.ui-select__trigger:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.ui-select__trigger:focus-visible,
.ui-select--open .ui-select__trigger {
  border-color: var(--focus);
  outline: none;
  box-shadow: var(--focus-ring);
}

.ui-select__value {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-select__value--placeholder {
  color: var(--text-faint);
}

.ui-select__chevron {
  display: grid;
  flex: none;
  color: var(--text-faint);
  transition: transform var(--duration-fast) var(--ease-out);
}

.ui-select--open .ui-select__chevron {
  transform: rotate(180deg);
}

/* Portaled to <body> with position: fixed so no scrolling ancestor clips
   it; select.rs computes top/bottom/left/width from the trigger. */
.ui-select__panel {
  position: fixed;
  z-index: var(--z-popover);
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: min(18rem, 50dvh, var(--panel-room, 18rem));
  padding: var(--space-1);
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
  box-shadow: var(--shadow-popover);
}

.ui-select__option {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: var(--control-sm);
  padding: 0 var(--space-2);
  border-radius: var(--radius-md);
  color: var(--text-dim);
  font-size: var(--text-13);
  cursor: pointer;
}

.ui-select__option--active {
  background: var(--bg-hover);
  color: var(--text);
}

.ui-select__option[aria-selected="true"] {
  color: var(--text);
}

.ui-select__check {
  display: grid;
  flex: none;
  color: var(--accent-text);
}

.ui-select__empty {
  padding: var(--space-2);
  color: var(--text-dim);
  font-size: var(--text-13);
}

/* ── Popover and menu ─────────────────────────────────────────────────── */
/* The one floating-panel look, shared with the Select list. popover.rs
   portals it to <body> and sets left/width/top|bottom and --panel-room
   (the height left on its side of the anchor). */
.ui-popover {
  position: fixed;
  z-index: var(--z-popover);
  display: flex;
  flex-direction: column;
  max-height: min(36rem, var(--panel-room, 36rem));
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
  box-shadow: var(--shadow-popover);
  color: var(--text);
}

/* A group of rows inside a popover; groups are divided by a hairline. */
.ui-menu {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: var(--space-1);
}

.ui-menu + .ui-menu {
  border-top: 1px solid var(--line);
}

.ui-menu__label {
  padding: var(--space-2) var(--space-2) var(--space-1);
  color: var(--text-dim);
  font-size: var(--text-12);
  font-weight: var(--weight-medium);
}

/* A row: optional icon or tile, name over an optional hint, and an end
   mark (check, badge, spinner). Rows are links or buttons. */
.ui-menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--control-sm);
  padding: var(--space-1) var(--space-2);
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: var(--text-13);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.ui-menu__item:hover,
.ui-menu__item:focus-visible {
  background: var(--bg-hover);
  color: var(--text);
}

.ui-menu__item:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.ui-menu__item:is([aria-current="page"], [aria-checked="true"]) {
  color: var(--text);
}

.ui-menu__item:is(:disabled, [aria-disabled="true"]) {
  cursor: not-allowed;
  opacity: 0.6;
}

.ui-menu__icon {
  display: grid;
  flex: none;
  place-items: center;
  width: var(--icon-md);
  color: var(--text-dim);
}

.ui-menu__tile {
  display: grid;
  flex: none;
  place-items: center;
  width: var(--tile);
  height: var(--tile);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  color: var(--text-dim);
}

.ui-menu__text {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-width: 0;
}

.ui-menu__name {
  overflow: hidden;
  color: var(--text);
  font-weight: var(--weight-medium);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-menu__hint {
  overflow: hidden;
  color: var(--text-dim);
  font-size: var(--text-12);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-menu__end {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--space-1);
  margin-left: auto;
  color: var(--accent-text);
}

/* A small busy ring, sized by the font: a row being switched to. */
.ui-spinner {
  display: inline-block;
  flex: none;
  width: 1em;
  height: 1em;
  border: 2px solid var(--line-strong);
  border-top-color: var(--accent);
  border-radius: var(--radius-full);
  animation: ui-spin 0.8s linear infinite;
}

@keyframes ui-spin {
  to { transform: rotate(360deg); }
}

.ui-menu__divider {
  height: 1px;
  margin: var(--space-1) 0;
  border: 0;
  background: var(--line);
}

/* ── Segmented control: one of a few views, as pressed toggle buttons ─── */
.ui-segmented {
  display: inline-flex;
  flex: none;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
}

.ui-segmented__option {
  height: calc(var(--control-md) - 6px);
  padding: 0 var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-dim);
  font-size: var(--text-13);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  cursor: pointer;
}

.ui-segmented__option:hover {
  color: var(--text);
}

.ui-segmented__option[aria-pressed="true"] {
  background: var(--bg-hover);
  color: var(--text);
}

/* Choice cards: a few mutually exclusive options that each need a sentence
   of explanation (what an API key is for). */
.ui-choice-cards {
  display: grid;
  gap: var(--space-2);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
}
.ui-choice-card {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  color: var(--text);
  text-align: left;
  font: inherit;
  cursor: pointer;
}
.ui-choice-card:hover { background: var(--bg-hover); }
.ui-choice-card[aria-pressed="true"] {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.ui-choice-card:disabled { opacity: 0.55; cursor: not-allowed; }
.ui-choice-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ui-choice-card__title { font-size: var(--text-13); font-weight: var(--weight-semibold); }
.ui-choice-card__text { color: var(--text-dim); font-size: var(--text-12); overflow-wrap: anywhere; }

/* Badges side by side in a cell. */
.ui-badges { display: inline-flex; flex-wrap: wrap; gap: var(--space-1); }

/* A folded-away part of a form. */
.ui-details > summary { cursor: pointer; font-size: var(--text-13); font-weight: var(--weight-semibold); }
.ui-details[open] > summary { margin-bottom: var(--space-3); }

.ui-segmented__option:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.ui-segmented__option:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
}

/* ── Tabs ─────────────────────────────────────────────────────────────── */
/* Underline tabs: links (aria-current) or buttons (role=tab). Scrolls
   sideways on narrow widths instead of wrapping into a second row. */
.ui-tabs {
  display: flex;
  gap: var(--space-1);
  overflow-x: auto;
  border-bottom: 1px solid var(--line);
  scrollbar-width: none;
}

/* More tabs beyond an edge: that edge fades out (ViewTabs measures). */
.ui-tabs--more-end {
  mask-image: linear-gradient(to right, #000 calc(100% - var(--space-10)), transparent);
}

.ui-tabs--more-start {
  mask-image: linear-gradient(to left, #000 calc(100% - var(--space-10)), transparent);
}

.ui-tabs--more-start.ui-tabs--more-end {
  mask-image: linear-gradient(to right, transparent, #000 var(--space-10), #000 calc(100% - var(--space-10)), transparent);
}

.ui-tabs__tab {
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--space-2);
  height: var(--control-lg);
  padding: 0 var(--space-3);
  border: 0;
  background: none;
  color: var(--text-dim);
  font-size: var(--text-13);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
}

.ui-tabs__tab:hover {
  color: var(--text);
}

.ui-tabs__tab:focus-visible {
  outline-offset: -2px;
}

.ui-tabs__tab[aria-selected="true"],
.ui-tabs__tab[aria-current="page"] {
  color: var(--text);
}

.ui-tabs__tab[aria-selected="true"]::after,
.ui-tabs__tab[aria-current="page"]::after {
  content: "";
  position: absolute;
  right: var(--space-3);
  bottom: 0;
  left: var(--space-3);
  height: 2px;
  border-radius: var(--radius-full);
  background: var(--accent);
}

/* ── Badge ────────────────────────────────────────────────────────────── */
/* Counts and short labels. Tone modifiers carry state, never decoration. */
.ui-badge {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--space-1);
  height: 20px;
  padding: 0 var(--space-2);
  border-radius: var(--radius-full);
  background: var(--neutral-soft);
  color: var(--text-dim);
  font-size: var(--text-12);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;
}

.ui-badge--success { background: var(--success-soft); color: var(--success); }
.ui-badge--warning { background: var(--warning-soft); color: var(--warning); }
.ui-badge--danger { background: var(--danger-soft); color: var(--danger); }
.ui-badge--accent { background: var(--accent-soft); color: var(--accent-text); }

/* ── Chip: a small clickable fact ("OpenCode", "2 CPU · 4 GiB"); the
   warning variant names what is still missing. ─────────────────────── */
.ui-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: 22px;
  padding: 2px var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-full);
  background: var(--bg-raised);
  color: var(--text-dim);
  font: inherit;
  font-size: var(--text-12);
  cursor: pointer;
}
.ui-chip:hover { border-color: var(--line-strong); color: var(--text); }
.ui-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.ui-chip--warning { border-color: transparent; background: var(--warning-soft); color: var(--warning); }

/* ── Status ───────────────────────────────────────────────────────────── */
/* One status system: a dot plus a label. The label is always present;
   colour is never the only signal. */
.ui-status-indicator {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  max-width: 100%;
  color: var(--text);
  font-size: var(--text-13);
  white-space: nowrap;
}

.ui-status-indicator > :last-child {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ui-status-dot {
  display: inline-block;
  flex: none;
  width: var(--dot);
  height: var(--dot);
  border-radius: var(--radius-full);
  background: currentColor;
  color: var(--neutral);
}

.ui-status-dot--success { color: var(--success); }
.ui-status-dot--warning { color: var(--warning); }
.ui-status-dot--danger { color: var(--danger); }
.ui-status-dot--neutral { color: var(--neutral); }
/* In use and fine: allocated scheduler nodes. */
.ui-status-dot--info { color: var(--info); }

/* Live state only: a soft ring that expands from a running dot. Drawn on a
   pseudo-element that only scales and fades, which the compositor animates
   without the main thread; an animated box-shadow repainted every frame,
   for as long as the page was open. */
.ui-status-dot--pulse {
  position: relative;
}

.ui-status-dot--pulse::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0;
  animation: ui-pulse 2s var(--ease-out) infinite;
}

/* Out to 5px around the 8px dot, as the ring was. */
@keyframes ui-pulse {
  0% { transform: scale(1); opacity: 0.45; }
  70%, 100% { transform: scale(2.25); opacity: 0; }
}

.ui-health-indicator {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  min-width: 0;
}

.ui-health-indicator > .ui-status-dot {
  margin-top: calc((1lh - var(--dot)) / 2);
}

.ui-health-indicator__label {
  color: var(--text);
  font-size: var(--text-13);
  font-weight: var(--weight-medium);
}

.ui-health-indicator__supporting {
  color: var(--text-dim);
  font-size: var(--text-12);
}

/* ── Meter: how full something is, as a short bar beside its figure ──── */
/* The figure carries the value; the bar only lets a column be scanned. */
.ui-meter {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  max-width: 100%;
}

.ui-meter__track {
  flex: none;
  width: var(--meter-width, 3rem);
  height: var(--space-1);
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--bg-hover);
}

.ui-meter__fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--chart-1);
}

.ui-meter__value {
  min-width: 0;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Under a figure: the bar takes the width its label leaves. */
.ui-meter--block {
  display: flex;
  width: 100%;
}

.ui-meter--block .ui-meter__track {
  flex: 1;
}

/* ── State bar: how a total splits by state, above its counts ─────────── */
.ui-state-bar {
  display: flex;
  height: var(--space-1);
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--bg-hover);
}

/* Sized by count; the smallest share still shows. */
.ui-state-bar__part {
  flex-basis: 0;
  min-width: var(--space-1);
}

.ui-state-bar__part--success { background: var(--success); }
.ui-state-bar__part--warning { background: var(--warning); }
.ui-state-bar__part--danger { background: var(--danger); }
.ui-state-bar__part--neutral { background: var(--neutral); }

/* ── Panel ────────────────────────────────────────────────────────────── */
/* The one in-flow box: a hairline, one surface step, no shadow. It owns
   the rhythm of what it holds, and is the positioning context for what it
   holds (a stretched link covers the panel, not the page). */
.ui-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
  padding: clamp(var(--space-4), 3cqi, var(--space-6));
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
}

/* Nested flex/grid content must shrink with the card, not cover its neighbour. */
.ui-panel > * {
  min-width: 0;
}

/* ── Section header ───────────────────────────────────────────────────── */
.ui-section-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-3) var(--space-4);
  min-width: 0;
}

.ui-section-header__text {
  min-width: 0;
  max-width: var(--prose-max);
}

.ui-section-header__heading {
  display: flex;
  flex-wrap: wrap;
  min-width: 0;
  align-items: center;
  gap: var(--space-2);
}

.ui-section-header__title {
  overflow-wrap: anywhere;
  font-size: var(--text-16);
  line-height: var(--leading-tight);
}

.ui-section-header__description {
  margin-top: var(--space-1);
  color: var(--text-dim);
  font-size: var(--text-13);
}

.ui-section-header__actions {
  display: flex;
  min-width: 0;
  max-width: 100%;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

/* ── Metrics ──────────────────────────────────────────────────────────── */
/* A metric row is one strip divided by hairlines, not a row of cards. The
   cells' shadows draw the dividers; the strip's border clips the outer
   ones, so a short last row leaves no stray lines. */
.ui-metric-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
}

.ui-metric-grid > * {
  box-shadow: 1px 0 0 var(--line), 0 1px 0 var(--line);
}

.ui-metric-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  padding: var(--space-4) var(--space-5);
}

.ui-metric-panel__label {
  color: var(--text-dim);
  font-size: var(--text-13);
}

.ui-metric-panel__value {
  overflow: hidden;
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-24);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-metric-panel__unit {
  margin-left: var(--space-1);
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--text-13);
  font-weight: var(--weight-regular);
  letter-spacing: normal;
}

.ui-metric-panel__value--success { color: var(--success); }
.ui-metric-panel__value--warning { color: var(--warning); }
.ui-metric-panel__value--danger { color: var(--danger); }
.ui-metric-panel__value--neutral { color: var(--text); }

.ui-metric-panel__detail {
  color: var(--text-dim);
  font-size: var(--text-12);
  overflow-wrap: anywhere;
}

/* Phones: two figures a row instead of one tall column. */
@container main (max-width: 520px) {
  .ui-metric-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .ui-metric-panel {
    padding: var(--space-3) var(--space-4);
  }

  .ui-metric-panel__value {
    font-size: var(--text-20);
  }
}

/* ── Status summary: a quiet row of counts above a list ──────────────── */
.ui-status-summary {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Holds the row's place while the list loads. */
.ui-status-summary__skeleton {
  width: min(100%, 16rem);
  height: 20px;
}

/* ── Toolbar: search and filters above a list ────────────────────────── */
.ui-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.ui-toolbar__search {
  flex: 1 1 16rem;
  min-width: 0;
}

.ui-toolbar > .ui-select {
  flex: 0 1 12rem;
  min-width: 9rem;
}

@container main (max-width: 520px) {
  .ui-toolbar > .ui-select {
    flex: 1 1 9rem;
  }
}

/* ── Facts: short label-over-value pairs that flow into columns ──────── */
/* <dl class="ui-facts"><div><dt>…</dt><dd>…</dd></div>…</dl> */
/* --facts-min: the narrowest a column may get before the facts reflow. */
.ui-facts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--facts-min, 13rem)), 1fr));
  gap: var(--space-5) var(--space-6);
  margin: 0;
}

.ui-facts > div {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.ui-facts dt {
  color: var(--text-dim);
  font-size: var(--text-12);
}

.ui-facts dd {
  margin: 0;
  color: var(--text);
  font-size: var(--text-13);
  overflow-wrap: anywhere;
}

/* Two columns on a phone rather than one long list. */
@container main (max-width: 520px) {
  .ui-facts {
    --facts-min: 8rem;
  }
}

/* A long value (a key, a fingerprint) takes the whole row. */
.ui-facts__wide {
  grid-column: 1 / -1;
}

/* ── Disclosure: <details class="ui-disclosure"><summary>… ────────────── */
.ui-disclosure > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--text-dim);
  font-size: var(--text-13);
  list-style: none;
  cursor: pointer;
}

.ui-disclosure > summary::-webkit-details-marker {
  display: none;
}

/* A chevron drawn in the text colour: right when closed, down when open. */
.ui-disclosure > summary::before {
  content: "";
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--duration-fast) var(--ease-out);
}

.ui-disclosure[open] > summary::before {
  transform: rotate(45deg);
}

.ui-disclosure > summary:hover {
  color: var(--text);
}

.ui-disclosure[open] > summary {
  margin-bottom: var(--space-3);
}

/* ── Key-value list ───────────────────────────────────────────────────── */
/* <dl class="ui-kv"><div><dt>…</dt><dd>…</dd></div>…</dl> */
.ui-kv {
  display: grid;
  grid-template-columns: fit-content(40%) minmax(0, 1fr);
  gap: var(--space-3) var(--space-6);
  margin: 0;
  font-size: var(--text-13);
}

.ui-kv > div {
  display: contents;
}

.ui-kv dt {
  color: var(--text-dim);
  min-width: 0;
  overflow-wrap: anywhere;
}

.ui-kv dd {
  min-width: 0;
  margin: 0;
  color: var(--text);
  overflow-wrap: anywhere;
}

@container main (max-width: 520px) {
  .ui-kv {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-1);
  }

  .ui-kv > dd + dt,
  .ui-kv > div + div > dt {
    margin-top: var(--space-2);
  }
}

/* ── Timeline ─────────────────────────────────────────────────────────── */
/* <ol class="ui-timeline"><li class="ui-timeline__item"><span dot>
   <div class="ui-timeline__body">…</div></li></ol> */
.ui-timeline {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ui-timeline__item {
  position: relative;
  display: grid;
  grid-template-columns: var(--dot) minmax(0, 1fr);
  gap: var(--space-3);
  padding-bottom: var(--space-5);
}

.ui-timeline__item > .ui-status-dot {
  margin-top: calc((1lh - var(--dot)) / 2);
}

/* The rail joining one event's dot to the next. */
.ui-timeline__item:not(:last-child)::before {
  content: "";
  position: absolute;
  top: calc(1lh + var(--space-1));
  bottom: var(--space-1);
  left: calc(var(--dot) / 2 - 0.5px);
  width: 1px;
  background: var(--line-strong);
}

.ui-timeline__item:last-child {
  padding-bottom: 0;
}

.ui-timeline__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  font-size: var(--text-13);
}

.ui-timeline__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
}

.ui-timeline__title {
  color: var(--text);
  font-weight: var(--weight-medium);
}

.ui-timeline__meta {
  color: var(--text-dim);
  font-size: var(--text-12);
}

/* What happened, in a line: an explanation or the event's fields. */
.ui-timeline__detail {
  color: var(--text-dim);
  font-size: var(--text-12);
  overflow-wrap: anywhere;
}

.ui-timeline__detail--danger {
  color: var(--danger);
}

/* ── Empty state ──────────────────────────────────────────────────────── */
.ui-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-12) var(--space-6);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  text-align: center;
}

.ui-empty-state__icon {
  display: grid;
  place-items: center;
  width: var(--control-lg);
  height: var(--control-lg);
  margin-bottom: var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  color: var(--text-dim);
}

.ui-empty-state--failure .ui-empty-state__icon {
  border-color: var(--danger-line);
  background: var(--danger-soft);
  color: var(--danger);
}

.ui-empty-state__title {
  font-size: var(--text-14);
}

.ui-empty-state__explanation {
  max-width: 48ch;
  color: var(--text-dim);
  font-size: var(--text-13);
  overflow-wrap: anywhere;
}

.ui-empty-state__action {
  margin-top: var(--space-3);
}

/* ── Error block: what failed, why, Try again, Details ──────────────── */
/* In a table's error row, a chart's box, or an empty state's frame. */
.ui-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  text-align: center;
}

.ui-error__title {
  margin: 0;
  color: var(--danger);
  font-size: var(--text-14);
  font-weight: var(--weight-semibold);
}

/* In an empty state's frame the icon carries the tone. */
.ui-empty-state .ui-error__title {
  color: var(--text);
}

.ui-error__message {
  max-width: 48ch;
  margin: 0;
  color: var(--text-dim);
  font-size: var(--text-13);
  overflow-wrap: anywhere;
}

.ui-error > .ui-button {
  margin-top: var(--space-2);
}

.ui-error-details {
  max-width: 100%;
}

.ui-error-details > summary {
  font-size: var(--text-12);
}

.ui-error-details[open] > summary {
  margin-bottom: var(--space-2);
}

.ui-error-details__panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.ui-error-details .ui-kv {
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-1) var(--space-4);
  max-width: 100%;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  font-size: var(--text-12);
  text-align: left;
}

/* Sections hidden while one failure stands for them all (OutageGroup):
   they stay mounted, so they keep refreshing. */
.ui-outage-group {
  display: contents;
}

.ui-outage-group[hidden] {
  display: none;
}

.ui-outage-group > * {
  min-width: 0;
}

/* A section showing its last answer after a refresh failed. */
.ui-refresh-failed {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--warning);
  font-size: var(--text-12);
  white-space: nowrap;
}

.ui-refresh-failed > span {
  color: var(--text-dim);
}

/* ── Inline notice ────────────────────────────────────────────────────── */
.ui-inline-notice {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  color: var(--text);
  font-size: var(--text-13);
}

.ui-inline-notice__icon {
  display: grid;
  flex: none;
  height: 1lh;
  place-items: center;
  color: var(--text-dim);
}

.ui-inline-notice__message {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}

.ui-inline-notice__action {
  margin: calc(var(--space-1) * -1) 0;
}

/* Details of the failed request, on a line of their own under the message. */
.ui-inline-notice > .ui-error-details {
  flex-basis: 100%;
  padding-left: calc(var(--space-4) + var(--space-3));
}

.ui-inline-notice .ui-error-details__panel {
  align-items: flex-start;
}

.ui-inline-notice--success { border-color: transparent; background: var(--success-soft); }
.ui-inline-notice--warning { border-color: transparent; background: var(--warning-soft); }
.ui-inline-notice--danger { border-color: var(--danger-line); background: var(--danger-soft); }
.ui-inline-notice--success .ui-inline-notice__icon { color: var(--success); }
.ui-inline-notice--warning .ui-inline-notice__icon { color: var(--warning); }
.ui-inline-notice--danger .ui-inline-notice__icon { color: var(--danger); }

/* ── Skeleton ─────────────────────────────────────────────────────────── */
.ui-skeleton-group {
  display: contents;
}

.ui-skeleton__bar {
  display: block;
  height: var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--bg-hover);
  animation: ui-shimmer 1.6s ease-in-out infinite;
}

@keyframes ui-shimmer {
  50% { opacity: 0.45; }
}

.ui-skeleton {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

.ui-skeleton--card {
  padding: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
}

.ui-skeleton--metric {
  padding: var(--space-4) var(--space-5);
}

.ui-skeleton--metric .ui-skeleton__bar:last-child {
  height: var(--space-6);
}

.ui-skeleton--row {
  flex-direction: row;
  align-items: center;
  gap: var(--space-4);
  height: var(--row-h);
  padding: 0 var(--space-4);
  border-bottom: 1px solid var(--line);
}

.ui-skeleton--row .ui-skeleton__bar {
  flex: 1;
}

.ui-skeleton .ui-skeleton__bar:nth-child(1) { width: 40%; }
.ui-skeleton .ui-skeleton__bar:nth-child(2) { width: 72%; }
.ui-skeleton .ui-skeleton__bar:nth-child(3) { width: 56%; }
.ui-skeleton .ui-skeleton__bar:nth-child(4) { width: 30%; }
.ui-skeleton--row .ui-skeleton__bar:nth-child(n) { width: auto; }

.ui-skeleton__line {
  width: 100%;
}

/* ── Copy button ──────────────────────────────────────────────────────── */
.ui-copy--copied,
.ui-copy--copied:not(:disabled):hover {
  color: var(--success);
}

/* A value with its copy button beside it. */
.ui-copy-value {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 100%;
  min-width: 0;
}

.ui-copy-value > :first-child {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* In a facts list the button overhangs the value's line rather than making
   it taller, so a copyable value lines up with the values beside it. */
.ui-facts dd > .ui-copy-value > .ui-copy {
  margin-block: calc(-1 * var(--space-2));
}

/* ── Code block ───────────────────────────────────────────────────────── */
/* The actions get their own column, so scrolled code never runs under
   them. */
.ui-code {
  display: flex;
  align-items: flex-start;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
}

.ui-code__pre {
  flex: 1;
  min-width: 0;
  margin: 0;
  padding: var(--space-3) var(--space-4);
  overflow-x: auto;
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-12);
  line-height: var(--leading-normal);
  white-space: pre;
  tab-size: 4;
}

.ui-code--wrap .ui-code__pre {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* RichTextEditor: a Markdown field edited as formatted text. */
.ui-rte {
  display: flex;
  flex-direction: column;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
}
.ui-rte:focus-within { border-color: var(--accent); }
.ui-rte.is-disabled { opacity: 0.6; }
.ui-rte__bar {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: var(--space-1);
  border-bottom: 1px solid var(--line);
}
.ui-rte__bar .ui-button[aria-pressed="true"] { background: var(--bg-selected); color: var(--text); }
.ui-rte__fallback.ui-input { border: 0; border-radius: inherit; min-height: calc(var(--rte-rows, 4) * 1.5em + var(--space-4)); }
.ui-rte__content {
  min-height: calc(var(--rte-rows, 4) * 1.5em);
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--space-2) var(--space-3);
  color: var(--text);
  font-size: var(--text-14);
  line-height: 1.5;
  outline: none;
  overflow-wrap: anywhere;
}
.ui-rte__content > * + * { margin-top: var(--space-2); }
.ui-rte__content :is(p, h1, h2, h3, ul, ol, pre, blockquote) { margin-block: 0; }
.ui-rte__content :is(h1, h2, h3) { font-size: var(--text-14); font-weight: 600; }
.ui-rte__content h1 { font-size: var(--text-16, 1rem); }
.ui-rte__content :is(ul, ol) { padding-left: var(--space-5, 1.25rem); }
.ui-rte__content ul { list-style: disc; }
.ui-rte__content ol { list-style: decimal; }
.ui-rte__content blockquote { padding-left: var(--space-3); border-left: 2px solid var(--line); color: var(--text-dim, var(--text)); }
.ui-rte__content code { font-family: var(--font-mono); font-size: 0.92em; padding: 0 3px; border-radius: var(--radius-sm); background: var(--bg-subtle); }
.ui-rte__content pre { padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); background: var(--bg-subtle); overflow-x: auto; }
.ui-rte__content pre code { padding: 0; background: none; }
.ui-rte__content p.is-editor-empty:first-child::before {
  content: attr(data-placeholder);
  float: left;
  height: 0;
  color: var(--text-faint);
  pointer-events: none;
}

.ui-code__actions {
  display: flex;
  flex-shrink: 0;
  gap: var(--space-1);
  padding: var(--space-1);
}

/* ── Timestamp ────────────────────────────────────────────────────────── */
.ui-timestamp {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Stretched link ───────────────────────────────────────────────────── */
/* Makes a whole card clickable from one real link. The card must be the
   positioning context (a Panel is); otherwise the link covers the page. */
.ui-stretched-link {
  text-decoration: none;
}

.ui-stretched-link::after {
  content: "";
  position: absolute;
  inset: 0;
  /* The card's corners, so the focus ring follows them. */
  border-radius: var(--radius-lg);
}

.ui-stretched-link:focus-visible {
  outline: none;
}

.ui-stretched-link:focus-visible::after {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

/* ── Entity references ────────────────────────────────────────────────── */
.ui-entity-reference {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  max-width: 100%;
  vertical-align: middle;
  flex-wrap: nowrap;
  color: var(--text-dim);
  line-height: var(--leading-snug);
}
.ui-entity-reference__identity {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}
.ui-entity-reference__icon {
  display: inline-flex;
  align-items: center;
  flex: none;
  color: var(--text-dim);
  width: 14px;
  height: 14px;
}
.ui-entity-reference__icon:empty { display: none; }
.ui-entity-reference__value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); font-size: var(--text-12); }
.ui-entity-reference__value--name { font-family: var(--font-sans); font-size: inherit; }
.ui-entity-reference button { flex-shrink: 0; }
.ui-entity-reference .ui-link { color: inherit; text-decoration: none; }
.ui-entity-reference .ui-link:hover { color: var(--text); text-decoration: underline; }
.ui-entity-reference .ui-copy { border: 0; background: transparent; }
.ui-entity-reference .ui-copy:not(:disabled):hover { background: transparent; }
@media (hover: hover) and (pointer: fine) and (min-width: 481px) {
  .ui-entity-reference .ui-copy { width: 24px; height: 24px; min-width: 24px; padding: 0; color: var(--text-dim); }
  .ui-entity-reference .ui-copy:hover { background: transparent; color: var(--text); }
}

/* ── Data table ───────────────────────────────────────────────────────── */
/* Scrolls sideways inside its own frame when the columns need more room
   than the page has; edge shadows show there is more. */
.ui-data-table {
  /* The containing block for visually-hidden labels inside, so they scroll
     with the table instead of widening the page. */
  position: relative;
  container: table / inline-size;
  min-width: 0;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(to right, var(--bg-raised) 40%, transparent) left / var(--space-8) 100% no-repeat local,
    linear-gradient(to left, var(--bg-raised) 40%, transparent) right / var(--space-8) 100% no-repeat local,
    linear-gradient(to right, var(--line-strong), transparent) left / var(--space-3) 100% no-repeat scroll,
    linear-gradient(to left, var(--line-strong), transparent) right / var(--space-3) 100% no-repeat scroll,
    var(--bg-raised);
}

.ui-data-table:focus-visible {
  outline-offset: 2px;
}

.ui-data-table table {
  width: 100%;
  /* --table-min-auto (set by DataTable) keeps every column readable when
     the fixed widths alone add up past the section's --table-min. */
  min-width: max(var(--table-min, 40rem), var(--table-min-auto, 0rem));
  border-collapse: collapse;
  table-layout: fixed;
}

/* Loading has columns; empty/error states have a message, not data to compare. */
.ui-data-table--message table { min-width: 0; }
.ui-data-table--message :is(colgroup, thead) { display: none; }

.ui-data-table th {
  height: var(--control-lg);
  padding: 0 var(--space-4);
  border-bottom: 1px solid var(--line);
  color: var(--text-dim);
  /* A column's classes style its cells' content, never its header. */
  font-family: var(--font-sans);
  font-size: var(--text-12);
  font-weight: var(--weight-medium);
  text-align: left;
  white-space: nowrap;
}

.ui-data-table td {
  height: var(--row-h);
  padding: 0 var(--space-4);
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  color: var(--text-dim);
  font-size: var(--text-13);
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Stacked identities and form controls determine row height. The fixed row
   baseline is only a minimum; do not clip their copy buttons or inputs. */
.ui-data-table td:has(.ui-cell-stack, .ui-entity-reference, .ui-input, .ui-select) { height: auto; padding-block: var(--space-2); }

.ui-data-table tbody tr:last-child td {
  border-bottom: 0;
}

.ui-data-table tbody tr:hover td {
  background: var(--bg-hover);
}

/* The first cell names the row; it reads at full strength. */
.ui-data-table td:first-child {
  color: var(--text);
}

.ui-data-table .ui-data-table__num {
  text-align: right;
}

.ui-data-table td.ui-data-table__num {
  font-family: var(--font-mono);
  font-size: var(--text-12);
  font-variant-numeric: tabular-nums;
}

/* Buttons and menus never clip: an actions cell overflows rather than
   cutting its controls. */
/* Row actions stay in view while a wide table scrolls sideways, on an
   opaque background so the cells passing beneath never show through. */
.ui-data-table .ui-data-table__actions {
  position: sticky;
  right: 0;
  overflow: visible;
  background: var(--bg-raised);
  text-align: right;
}

.ui-data-table tbody tr:hover td.ui-data-table__actions {
  background: linear-gradient(var(--bg-hover), var(--bg-hover)), var(--bg-raised);
}

/* Where the table scrolls, a hairline marks the edge the cells slide under. */
@container main (max-width: 720px) {
  .ui-data-table .ui-data-table__actions {
    box-shadow: inset 1px 0 0 var(--line);
  }

  /* The row's name stays in view too (after a row checkbox, when there is
     one); the columns between scroll beneath. */
  .ui-data-table th:first-child:not([colspan]),
  .ui-data-table td:first-child:not([colspan]),
  .ui-data-table .ui-data-table__select + th,
  .ui-data-table .ui-data-table__select + td {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--bg-raised);
    box-shadow: inset -1px 0 0 var(--line);
  }

  .ui-data-table th.ui-data-table__select,
  .ui-data-table td.ui-data-table__select {
    box-shadow: none;
  }

  .ui-data-table .ui-data-table__select + th,
  .ui-data-table .ui-data-table__select + td {
    left: var(--select-col);
  }

  .ui-data-table tbody tr:hover td:first-child,
  .ui-data-table tbody tr:hover .ui-data-table__select + td {
    background: linear-gradient(var(--bg-hover), var(--bg-hover)), var(--bg-raised);
  }
}

/* A table may be in a narrow card on a wide page. Freeze neither edge when
   there is not enough room for both; let every column scroll into view. */
@container table (max-width: 640px) {
  .ui-data-table th:first-child:not([colspan]),
  .ui-data-table td:first-child:not([colspan]),
  .ui-data-table .ui-data-table__select + th,
  .ui-data-table .ui-data-table__select + td,
  .ui-data-table .ui-data-table__actions {
    position: static;
    box-shadow: none;
  }
}

/* A phone has no room for a selectable table's name, status and a row of
   buttons at once: there the actions scroll with the middle columns. */
@container main (max-width: 480px) {
  .ui-data-table:has(.ui-data-table__select) .ui-data-table__actions {
    position: static;
    box-shadow: none;
  }
}

/* A row checkbox column (bulk selection). */
.ui-data-table {
  --select-col: 2.75rem;
}

.ui-data-table .ui-data-table__select {
  padding-right: 0;
}

.ui-data-table__select input {
  width: var(--icon-md);
  height: var(--icon-md);
  vertical-align: middle;
  accent-color: var(--accent);
}

.ui-data-table__actions > * {
  vertical-align: middle;
}

.ui-data-table__actions > * + * {
  margin-left: var(--space-2);
}

/* A navigable row: the primary cell holds a real link; data_table.rs
   forwards a click anywhere else on the row to it. */
.ui-data-table tr:has(.ui-data-table__link) {
  cursor: pointer;
}

/* Truncates itself (full name in `title`) so the cell never clips it. */
.ui-data-table__link {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  color: var(--text);
  font-weight: var(--weight-medium);
  text-decoration: none;
  text-overflow: ellipsis;
  vertical-align: middle;
  white-space: nowrap;
}

.ui-data-table tr:hover .ui-data-table__link {
  text-decoration: underline;
  text-decoration-color: var(--text-faint);
  text-underline-offset: 3px;
}

.ui-data-table__link:focus-visible {
  outline-offset: 1px;
}

/* A drawer-opening name uses the same visual language as a navigable row. */
.ui-data-table__open { padding: 0; border: 0; background: none; color: var(--text); text-align: left; font: inherit; font-weight: var(--weight-medium); cursor: pointer; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-data-table__open:hover { text-decoration: underline; }
@media (pointer: coarse), (max-width: 480px) {
  .ui-data-table__open { min-height: 44px; }
}
@container main (max-width: 540px) {
  .ui-data-table--cards table { min-width: 0; }
  .ui-data-table--cards :is(thead, colgroup) { display: none; }
  .ui-data-table--cards tr { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ui-data-table--cards td { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; height: auto; padding: var(--space-3); position: static; overflow: visible; box-shadow: none; white-space: normal; }
  .ui-data-table--cards td::before { content: attr(data-label); color: var(--text-dim); font-size: var(--text-12); }
  .ui-data-table--cards td:first-child, .ui-data-table--cards td[colspan] { grid-column: 1 / -1; }
  /* A number under its label reads from the left, like every other card cell. */
  .ui-data-table--cards td.ui-data-table__num { align-items: flex-start; text-align: left; }
  .ui-data-table--cards .ui-data-table__actions { align-items: flex-start; justify-content: flex-end; text-align: left; }
  .ui-data-table--cards .ui-cell-stack__secondary { flex-wrap: nowrap; }
  .ui-data-table--cards :is(.ui-data-table__open, .ui-data-table__link) { white-space: normal; overflow-wrap: anywhere; }
  .ui-data-table--cards tr:not(:last-child) { border-bottom: 2px solid var(--line-strong); }
}

.ui-data-table__sort {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0 calc(var(--space-1) * -1);
  padding: var(--space-1);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: inherit;
  font: inherit;
}

.ui-data-table__sort:hover,
.ui-data-table [aria-sort] .ui-data-table__sort {
  color: var(--text);
}

.ui-data-table__skeleton {
  display: block;
  width: 64%;
  height: var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--bg-hover);
  animation: ui-shimmer 1.6s ease-in-out infinite;
}

.ui-data-table tr:nth-child(2n) .ui-data-table__skeleton { width: 82%; }
.ui-data-table tr:nth-child(3n) .ui-data-table__skeleton { width: 48%; }

/* Empty and error rows span the table and read as an inline empty state. */
.ui-data-table .ui-data-table__message {
  height: auto;
  padding: var(--space-10) var(--space-6);
  white-space: normal;
  text-align: center;
}

.ui-data-table tbody tr:hover .ui-data-table__message {
  background: none;
}

.ui-data-table__message-title {
  display: block;
  color: var(--text);
  font-size: var(--text-14);
  font-weight: var(--weight-semibold);
}

.ui-data-table__message-text {
  display: block;
  max-width: 48ch;
  margin: var(--space-1) auto 0;
  color: var(--text-dim);
  overflow-wrap: anywhere;
}


/* ── Overlay: modal and drawer ────────────────────────────────────────── */
body.ui-overlay-open {
  overflow: hidden;
}

.ui-overlay {
  position: fixed;
  z-index: var(--z-overlay);
  inset: 0;
  visibility: hidden;
  pointer-events: none;
  /* Keep the backdrop/panel visible while their existing exit transitions
     finish. Interaction and accessibility are disabled immediately. */
  transition: visibility 0s linear var(--duration-base);
}

.ui-overlay--open {
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

@media (prefers-reduced-motion: reduce) {
  .ui-overlay { transition: none; }
}

.ui-overlay__backdrop {
  position: absolute;
  inset: 0;
  background: var(--scrim);
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
}

.ui-overlay--open .ui-overlay__backdrop {
  opacity: 1;
}

.ui-overlay__panel {
  position: absolute;
  /* Portaled forms measure the dialog, never the wider page behind it. */
  container: main / inline-size;
  display: flex;
  flex-direction: column;
  min-width: 0;
  border: 1px solid var(--line-strong);
  background: var(--bg-raised);
  box-shadow: var(--shadow-overlay);
}

.ui-overlay__panel--modal {
  top: 50%;
  left: 50%;
  width: min(30rem, calc(100vw - 2 * var(--space-4)));
  max-height: calc(100dvh - 2 * var(--space-8));
  border-radius: var(--radius-lg);
  opacity: 0;
  transform: translate(-50%, calc(-50% + var(--space-2)));
  transition:
    opacity var(--duration-base) var(--ease-out),
    transform var(--duration-base) var(--ease-out);
}

.ui-overlay--open .ui-overlay__panel--modal {
  opacity: 1;
  transform: translate(-50%, -50%);
}

.ui-overlay__panel--drawer {
  top: 0;
  right: 0;
  bottom: 0;
  width: min(var(--drawer-width), 100vw);
  border-width: 0 0 0 1px;
  /* A table in a drawer fits the drawer, not a page. */
  --table-min: 24rem;
  transform: translateX(100%);
  transition: transform var(--duration-base) var(--ease-out);
}

.ui-overlay--open .ui-overlay__panel--drawer {
  transform: none;
}

.ui-overlay__header {
  display: flex;
  flex: none;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-5) var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--line);
}

.ui-overlay__header > div {
  min-width: 0;
}

.ui-overlay__title {
  font-size: var(--text-16);
  line-height: var(--leading-snug);
  overflow-wrap: anywhere;
}

.ui-overlay__description {
  max-width: var(--prose-max);
  margin-top: var(--space-1);
  color: var(--text-dim);
  font-size: var(--text-13);
}

.ui-overlay__close {
  margin: calc(var(--space-1) * -1) 0;
}

.ui-overlay__body {
  flex: 1;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* A form inside a drawer: the fields scroll, the actions stay pinned. */
.ui-drawer-form {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

.ui-drawer-form__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
}

.ui-drawer-form__footer {
  position: sticky;
  bottom: 0;
  display: flex;
  flex-wrap: wrap;
  z-index: var(--z-sticky);
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--line);
  background: var(--bg-raised);
}

.ui-confirm__content {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
}

.ui-confirm__target {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
}

.ui-confirm__target strong {
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-13);
  font-weight: var(--weight-medium);
  overflow-wrap: anywhere;
}

.ui-confirm__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--line);
  background: var(--bg-subtle);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
/* Facts in a dialog sit two to a row. */
.ui-confirm__content .ui-facts {
  --facts-min: 10rem;
}

/* A second way out of the dialog, kept apart from Cancel and the confirm. */
.ui-confirm__aside {
  margin-right: auto;
}

/* ── Chart ────────────────────────────────────────────────────────────── */
/* Drawn at the measured pixel width (time_series_chart.rs), so type never
   stretches. Series colour arrives as --series from the --chart-n tokens. */
.ui-chart {
  min-width: 0;
  margin: 0;
}

.ui-chart__controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.ui-chart__controls > .ui-select {
  width: auto;
  min-width: 11rem;
}

.ui-chart__unit {
  margin-bottom: var(--space-1);
  color: var(--text-dim);
  font-size: var(--text-12);
}

.ui-chart__plot {
  position: relative;
  height: 240px;
  border-radius: var(--radius-sm);
}

.ui-chart__plot:focus-visible {
  outline-offset: 4px;
}

.ui-chart__svg {
  display: block;
  overflow: visible;
}

.ui-chart__grid {
  stroke: var(--chart-grid);
}

.ui-chart__baseline {
  stroke: var(--line-strong);
}

.ui-chart__tick {
  fill: var(--text-faint);
  font-family: var(--font-mono);
  font-size: var(--text-11);
  font-variant-numeric: tabular-nums;
}

.ui-chart__line {
  fill: none;
  stroke: var(--series);
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ui-chart__dot {
  fill: var(--series);
}

.ui-chart__bar {
  fill: var(--chart-1);
  opacity: 0.8;
  transition: opacity var(--duration-fast) var(--ease-out);
}

.ui-chart__bar--active {
  opacity: 1;
}

.ui-chart__hit {
  fill: transparent;
}

.ui-chart__crosshair {
  stroke: var(--text-faint);
  stroke-dasharray: 2 3;
}

.ui-chart__marker {
  fill: var(--bg-raised);
  stroke: var(--series);
  stroke-width: 2;
}

/* Beside the crosshair; `--left` flips it to the other side near the
   right edge. */
.ui-chart__tooltip {
  position: absolute;
  top: 0;
  z-index: var(--z-popover);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 10rem;
  max-width: 18rem;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  box-shadow: var(--shadow-popover);
  font-size: var(--text-12);
  pointer-events: none;
  transform: translateX(var(--space-3));
}

.ui-chart__tooltip--left {
  transform: translateX(calc(-100% - var(--space-3)));
}

.ui-chart__tooltip-time {
  color: var(--text-dim);
}

.ui-chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-12);
}

.ui-chart__series {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

/* A short stroke, like the line it keys, so it never reads as a status dot. */
.ui-chart__swatch {
  flex: none;
  width: var(--space-3);
  height: 3px;
  border-radius: var(--radius-full);
  background: var(--series);
}

.ui-chart__series-label {
  min-width: 0;
  overflow: hidden;
  color: var(--text-dim);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-chart__series-value {
  margin-left: auto;
  padding-left: var(--space-2);
  color: var(--text);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Loading, empty and error in the plot's own footprint, so nothing jumps
   when the data arrives. */
.ui-chart__empty {
  display: grid;
  place-items: center;
  height: 240px;
  margin: 0;
  /* A long message wraps and stays inside the footprint. */
  padding: var(--space-4);
  overflow: hidden;
  overflow-wrap: anywhere;
  border: 1px dashed var(--line);
  border-radius: var(--radius-md);
  color: var(--text-dim);
  font-size: var(--text-13);
  text-align: center;
}

/* A failure's Details open below it, so its box grows instead of clipping. */
.ui-chart__failure {
  height: auto;
  min-height: 240px;
  overflow: visible;
}

/* ── Terminal ─────────────────────────────────────────────────────────── */
/* A toolbar on the page's surface over a screen that stays dark in both
   themes. The frame's height comes from the viewport, never from the
   canvas, so the screen can be measured without the measure feeding
   itself. */
.ui-terminal {
  display: flex;
  flex-direction: column;
  height: clamp(20rem, calc(100dvh - 20rem), 60rem);
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--terminal-bg);
}

.ui-terminal__toolbar {
  display: flex;
  flex-wrap: wrap;
  flex: none;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-4);
  border-bottom: 1px solid var(--line);
  background: var(--bg-raised);
}

.ui-terminal__status {
  min-width: 0;
}

.ui-terminal__actions {
  display: flex;
  flex: none;
  gap: var(--space-1);
}

.ui-terminal__screen {
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  padding: var(--space-2) var(--space-3);
  background: var(--terminal-bg);
  cursor: text;
}

.ui-terminal__screen:focus {
  outline: none;
}

.ui-terminal__screen:focus-visible {
  box-shadow: inset 0 0 0 2px var(--accent-soft);
}

.ui-terminal__screen canvas {
  display: block;
}

.ui-terminal__note {
  flex: none;
  margin: 0;
  padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--line);
  background: var(--bg-raised);
  color: var(--text-dim);
  font-size: var(--text-12);
}

/* Full screen: over the whole app, edge to edge. */
.ui-terminal--fullscreen {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  height: auto;
  border: 0;
  border-radius: 0;
}

/* ── Node groups: the add/remove flows, group cards, the live verdict ──── */
.pl-steps {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
  padding: 0;
  list-style: none;
  font-size: var(--text-12);
}

.pl-steps__item {
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-full);
  color: var(--text-dim);
}

.pl-steps__item--on {
  border-color: var(--accent);
  color: var(--text);
  font-weight: 600;
}

.pl-groups {
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.pl-group {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.pl-group:hover:not(:disabled) {
  border-color: var(--accent);
}

.pl-group--on {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.pl-group:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.pl-group__why {
  color: var(--danger);
  font-size: var(--text-12);
}

.pl-verdict {
  display: grid;
  gap: var(--space-2);
  margin: var(--space-3) 0;
}

.pl-verdict__nodes {
  margin: 0;
  padding-left: var(--space-5);
  font-size: var(--text-12);
}

.pl-review {
  display: grid;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.pl-review ul {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding-left: var(--space-5);
}

.pl-review__warn {
  color: var(--danger);
  font-weight: 600;
}

.pl-fallback {
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}

.pl-fallback__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-left: auto;
}

/* ── Script editor ────────────────────────────────────────────────────── */
/* A terminal that follows the theme (--tty-*). A transparent textarea lies
   over the painted copy of its text (`ScriptEditor`): the two layers share
   every text metric below, or the caret drifts from the colours. The cell
   takes the paint's size and the screen scrolls both together. */
.ui-tty {
  display: flex;
  flex-direction: column;
  height: clamp(20rem, calc(100dvh - 22rem), 44rem);
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--tty-bg);
  color: var(--tty-fg);
  transition: border-color var(--duration-fast) var(--ease-out);
}

.ui-tty:not(.ui-tty--full):has(.ui-tty__input:focus) {
  border-color: var(--focus);
  box-shadow: var(--focus-ring);
}

/* Full screen: over the whole app, edge to edge. */
.ui-tty--full {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  height: auto;
  border: 0;
  border-radius: 0;
}

/* Read only: as tall as the text (to a limit), and the painted text is
   what a pointer selects. */
.ui-tty--static:not(.ui-tty--full) {
  height: auto;
}

.ui-tty--static:not(.ui-tty--full) .ui-tty__screen {
  max-height: 44rem;
}

.ui-tty--static .ui-tty__paint {
  pointer-events: auto;
  user-select: text;
}

.ui-tty--static .ui-tty__paint ::selection {
  background: var(--tty-selection);
}

.ui-tty--static:not(.ui-tty--full):has(.ui-tty__screen:focus-visible) {
  border-color: var(--focus);
  box-shadow: var(--focus-ring);
}

.ui-tty--static .ui-tty__screen:focus-visible {
  outline: none;
}

.ui-tty__tab--static {
  display: inline-flex;
  align-items: center;
  overflow: hidden;
  border-color: transparent;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-tty__tab--static:hover {
  border-color: transparent;
}

.ui-tty__bar,
.ui-tty__status {
  display: flex;
  flex: none;
  align-items: center;
  min-width: 0;
  background: var(--tty-bar-bg);
}

.ui-tty__bar {
  gap: var(--space-3);
  padding: var(--space-1) var(--space-1) var(--space-1) var(--space-3);
  border-bottom: 1px solid var(--tty-line);
}

.ui-tty__dots {
  display: inline-flex;
  flex: none;
  gap: var(--space-1);
}

.ui-tty__dots i {
  width: var(--dot);
  height: var(--dot);
  border-radius: var(--radius-full);
  background: var(--tty-line);
}

.ui-tty__tab {
  min-width: 0;
  height: var(--control-sm);
  padding: 0 var(--space-2);
  border: 1px solid var(--tty-line);
  border-radius: var(--radius-md);
  background: var(--tty-bg);
  color: var(--tty-fg);
  font-family: var(--font-mono);
  font-size: var(--tty-text);
}

.ui-tty__tab:hover {
  border-color: var(--tty-gutter-fg);
}

.ui-tty__tab:focus {
  border-color: var(--focus);
  outline: none;
  box-shadow: var(--focus-ring);
}

.ui-tty__tab[aria-invalid="true"] {
  border-color: var(--danger);
}

.ui-tty__lang {
  flex: none;
  color: var(--tty-dim);
  font-family: var(--font-mono);
  font-size: var(--text-12);
}

.ui-tty__actions {
  display: flex;
  flex: none;
  gap: var(--space-1);
  margin-left: auto;
}

.ui-tty__screen {
  /* The gutter: the widest line number plus room either side. */
  --tty-gutter-w: calc(var(--tty-digits, 2) * 1ch + 2 * var(--space-3));
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  font-family: var(--font-mono);
  font-size: var(--tty-text);
  cursor: text;
}

.ui-tty__cell {
  display: grid;
  width: max-content;
  min-width: 100%;
  min-height: 100%;
  background: linear-gradient(to right, var(--tty-gutter) var(--tty-gutter-w), var(--tty-line) 0 calc(var(--tty-gutter-w) + 1px), transparent 0);
}

.ui-tty--wrap .ui-tty__cell {
  width: 100%;
}

/* The shared metrics. `.ui-tty` in the input's selector outranks the
   kit's and the browser's textarea rules. */
.ui-tty__paint,
.ui-tty .ui-tty__input {
  grid-area: 1 / 1;
  box-sizing: border-box;
  margin: 0;
  padding: var(--space-3) var(--space-4) var(--space-3) calc(var(--tty-gutter-w) + var(--space-3));
  border: 0;
  font-family: var(--font-mono);
  font-size: var(--tty-text);
  font-variant-ligatures: none;
  line-height: var(--tty-row);
  letter-spacing: 0;
  tab-size: 4;
  white-space: pre;
  overflow-wrap: normal;
  word-break: normal;
}

.ui-tty--wrap .ui-tty__paint,
.ui-tty--wrap .ui-tty__input {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.ui-tty__paint {
  counter-reset: tty-ln;
  color: var(--tty-fg);
  pointer-events: none;
}

.ui-tty .ui-tty__input {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  resize: none;
  border-radius: 0;
  background: transparent;
  color: transparent;
  -webkit-text-fill-color: transparent;
  caret-color: var(--tty-cursor);
  outline: none;
  box-shadow: none;
}

.ui-tty__input::selection {
  background: var(--tty-selection);
}

/* One block per line; its number sits on the line's first row and stays
   put while long lines scroll sideways. Its margins cancel its width, so
   the text starts where the textarea's does. */
.tty-l {
  display: block;
  min-height: var(--tty-row);
}

.tty-l::before {
  position: sticky;
  left: 0;
  display: inline-block;
  box-sizing: border-box;
  width: var(--tty-gutter-w);
  margin-right: var(--space-3);
  margin-left: calc(-1 * (var(--tty-gutter-w) + var(--space-3)));
  padding-right: var(--space-3);
  background: var(--tty-gutter);
  box-shadow: inset -1px 0 0 var(--tty-line);
  color: var(--tty-gutter-fg);
  content: counter(tty-ln);
  counter-increment: tty-ln;
  text-align: right;
}

.tty-comment { color: var(--tty-comment); }
.tty-directive { color: var(--tty-directive); }
.tty-flag, .tty-keyword { color: var(--tty-keyword); }
.tty-builtin { color: var(--tty-builtin); }
.tty-string { color: var(--tty-string); }
.tty-variable { color: var(--tty-variable); }
.tty-number { color: var(--tty-number); }
.tty-operator { color: var(--tty-operator); }
.tty-heredoc { color: var(--tty-heredoc); }

.ui-tty__status {
  flex-wrap: wrap;
  gap: 0 var(--space-3);
  padding: var(--space-1) var(--space-3);
  border-top: 1px solid var(--tty-line);
  color: var(--tty-dim);
  font-family: var(--font-mono);
  font-size: var(--text-12);
}

.ui-tty__error {
  color: var(--danger);
}

.ui-tty__source {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  color: var(--tty-fg);
}

/* An action in the status line ("Reset to template"). */
.ui-tty__link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--tty-directive);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.ui-tty__link:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.ui-tty__hint {
  margin-left: auto;
}

/* Phones: the filename needs the room more than the decoration does. */
@media (max-width: 480px) {
  .ui-tty__dots {
    display: none;
  }
}

/* ── Brand marks: engines and GPU vendors beside their names ── */

.ui-brand {
  display: inline-flex;
  flex-shrink: 0;
  height: var(--brand-size);
  color: var(--text);
  vertical-align: middle;
}

.ui-brand svg {
  display: block;
  width: auto;
  height: 100%;
}

/* A template that runs no known engine: its code in the mark's place. */
.ui-brand-monogram {
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: var(--text-11);
  font-weight: var(--weight-semibold);
  letter-spacing: 0;
}

/* A model: its maker's mark (or first letter) in a 20px slot, then its name
   over its id. */
.ui-model-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  max-width: 100%;
}

.ui-model-label > .ui-brand,
.ui-model-label > .ui-brand-monogram {
  flex: none;
  justify-content: center;
  width: 20px;
  text-align: center;
}

.ui-model-label__text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* A mark and its name: "[NVIDIA] 8 × H100", "[vLLM] vLLM". */
.ui-brand-label {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  max-width: 100%;
  vertical-align: middle;
}

.ui-brand-label__text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A node to add to a reservation: + before the name, a check once added. */
.pl-node-chip[aria-pressed="true"] {
  border-color: var(--accent-line);
  background: var(--accent-soft);
}

/* ── Capacity chart: free CPUs, memory and GPU per node, with a request ── */
/* Label and figure on a line, the bar under them. Used is the muted fill,
   the request sits on top of it in the accent (red when it does not fit), and
   the rest of the visible track is what is left. */
.pl-capacity {
  display: grid;
  gap: var(--space-3);
}

.pl-capacity__node {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}

.pl-capacity__node--over {
  border-color: var(--danger-line);
}

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

.pl-capacity__holders,
.pl-capacity__figure {
  color: var(--text-dim);
  font-size: var(--text-12);
}

.pl-capacity__bar {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: var(--space-1) var(--space-2);
  font-size: var(--text-12);
}

.pl-capacity__figure {
  justify-self: end;
  text-align: right;
}

.pl-capacity__track {
  grid-column: 1 / -1;
  display: flex;
  height: 6px;
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--line-strong);
}

.pl-capacity__used {
  background: var(--text-faint);
}

.pl-capacity__ask {
  background: var(--accent);
}

.pl-capacity__ask--over {
  background: var(--danger);
}

.pl-capacity__figure {
  font-variant-numeric: tabular-nums;
}

.pl-capacity__reason {
  margin: 0;
  color: var(--danger);
  font-size: var(--text-12);
}

.pl-capacity__reason--quiet {
  color: var(--text-dim);
}

/* Reservation access: the terminal link, ssh copy and a no-GPU badge. */
.pl-access {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.pl-access__nogpu {
  padding: 0 var(--space-2);
  border: 1px solid var(--warning);
  border-radius: var(--radius-full);
  color: var(--warning);
  font-size: var(--text-12);
  cursor: help;
}

.pl-access__help {
  font-size: var(--text-12);
}

.pl-ssh__steps {
  margin: 0 0 var(--space-2);
  padding-left: var(--space-5);
}

.pl-access__later {
  color: var(--text-dim);
  font-size: var(--text-12);
}

/* A deployment's failure: the reason, and a way to its log. */
.infra-deployment__failure {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.infra-deployment__failure > :first-child {
  flex: 1 1 20rem;
}

/* The reason under a failing workload's status in the list. */
.pl-workload__why {
  max-width: 28rem;
  overflow: hidden;
  color: var(--danger);
  font-size: var(--text-12);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Two-line table cells ─────────────────────────────────────────────── */
/* Two lines in one cell: a name over its email or description. Each line
   truncates on its own; the full text is in `title`. */
.ui-cell-stack {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.ui-cell-stack__primary,
.ui-cell-stack__secondary,
.ui-truncate {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-cell-stack__primary {
  color: var(--text);
  font-weight: var(--weight-medium);
}

.ui-cell-stack__secondary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--text-dim);
  font-size: var(--text-12);
}

/* A badge after the secondary text keeps its size and wraps below it
   when the column is narrow, rather than squeezing the text away. */
.ui-cell-stack__secondary {
  flex-wrap: wrap;
  row-gap: var(--space-1);
}

.ui-cell-stack__secondary > .ui-truncate {
  max-width: 100%;
}

/* A secondary line that truncates as a whole (an email, "model · 2m ago")
   ends in an ellipsis instead of wrapping. */
.ui-cell-stack__secondary.ui-truncate {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-cell-stack__secondary .ui-badge {
  flex-shrink: 0;
}

/* A group of fields under a legend of its own (limits, days, weights). */
.ui-fieldset {
  display: grid;
  gap: var(--space-2);
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.ui-fieldset > legend { margin-bottom: var(--space-2); padding: 0; }
/* Limits sit under the form's other fields as a group of their own. */
.ui-limits > legend {
  color: var(--text);
  font-size: var(--text-14);
  font-weight: var(--weight-semibold);
}

/* ── Typeahead: a search box whose matches list under it ──────────────── */
/* In the flow, not a popover: inside drawers and dialogs nothing clips it. */
.ui-typeahead {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}

.ui-typeahead__list {
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: min(16rem, 40dvh);
  margin: 0;
  padding: var(--space-1);
  overflow-y: auto;
  overscroll-behavior: contain;
  list-style: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg);
  background: var(--bg-raised);
  box-shadow: var(--shadow-popover);
}

.ui-typeahead__option {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: var(--control-md, 2rem);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-md);
  color: var(--text-dim);
  font-size: var(--text-13);
  cursor: pointer;
}

.ui-typeahead__option > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ui-typeahead__option > :first-child {
  color: var(--text);
}

.ui-typeahead__option[aria-selected="true"] {
  background: var(--bg-hover);
  color: var(--text);
}

.ui-typeahead__picked {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  min-height: var(--control-md, 2rem);
}

.ui-typeahead__picked > :first-child {
  min-width: 0;
  overflow: hidden;
  color: var(--text);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Live: a list that refreshes itself, and the switch for it ─────────── */
.ui-live {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  color: var(--text-dim);
  font-size: var(--text-12);
}

/* The switch on its own line, at the end. */
.ui-live-bar {
  display: flex;
  justify-content: flex-end;
}

/* Selection and bulk actions above a table. */
.ui-bulkbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  min-height: var(--control-lg);
}

.ui-bulkbar__count {
  color: var(--text-dim);
  font-size: var(--text-13);
  font-variant-numeric: tabular-nums;
}

.ui-bulkbar__end {
  margin-left: auto;
}


/* ── Chart grid: two charts a row where they fit, one on a phone ─────── */
.ui-chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr));
  gap: var(--space-4);
}

/* Health banners stacked above a view. */
.ui-health {
  display: grid;
  gap: var(--space-2);
}

/* ── Before / after diff (audit entries) ───────────────────────────────── */
.ui-diff {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-13);
  table-layout: fixed;
}

.ui-diff th,
.ui-diff td {
  padding: var(--space-2);
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
  overflow-wrap: anywhere;
}

.ui-diff thead th {
  color: var(--text-dim);
  font-weight: var(--weight-medium);
}

.ui-diff tbody th {
  width: 34%;
  font-weight: var(--weight-medium);
}

.ui-diff__changed .ui-diff__before {
  background: var(--danger-soft);
  text-decoration: line-through;
  text-decoration-color: var(--danger);
}

.ui-diff__changed .ui-diff__after {
  background: var(--success-soft);
}

/* Saved filter presets above a filter panel (Tenancy Queue and Audit). */
.ui-presets {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  margin-bottom: var(--space-3);
}

.ui-presets .ui-field__label {
  margin: 0;
}

.ui-presets__select {
  flex: 0 1 18rem;
  min-width: 12rem;
}

@media (max-width: 640px) {
  .ui-presets__select {
    flex-basis: 100%;
  }
}
.ui-member-role {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-12);
  font-weight: var(--weight-medium);
}
.ui-member-role--warning { color: var(--warning); }
.ui-member-role--success { color: var(--success); }
.ui-member-role--neutral { color: var(--text-dim); }
.ui-metric-panel__heading { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.ui-metric-panel__icon { display: inline-flex; color: var(--text-dim); }
.team-account-icon { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-text); }
.team-account-heading { margin: 0; font-size: var(--text-14); font-weight: var(--weight-medium); }
.team-account-role { display: flex; align-items: center; gap: var(--space-1); margin-top: var(--space-1); font-size: var(--text-12); color: var(--accent-text); }
.team-resource-heading { display: flex; align-items: center; gap: var(--space-2); color: var(--info); }
.team-invite__role { display: flex; align-items: flex-start; gap: var(--space-2); margin-top: var(--space-1); font-size: var(--text-13); cursor: pointer; }
.team-invites__list { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-3); }
.team-invites__item { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-3); padding: var(--space-3) var(--space-4); background: var(--bg-surface); border: 1px solid var(--line); border-radius: var(--radius-md); }
.team-invites__team { display: flex; align-items: center; gap: var(--space-2); font-weight: var(--weight-medium); }
.team-invites__actions { display: flex; gap: var(--space-2); }

.access-account-banner { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: var(--space-3); background: var(--bg-subtle); border: 1px solid var(--line); border-radius: var(--radius-md); color: var(--text-dim); font-size: var(--text-12); }
.access-account-banner__content { display: flex; flex: 1 1 100%; min-width: 0; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.access-account-banner__description { flex: 1 1 100%; min-width: 0; overflow-wrap: anywhere; }
.access-account-banner .app-account-badge { max-width: 100%; }

/* Phone/touch ergonomics. Keep zoom and native scrolling enabled. */
@media (pointer: coarse), (max-width: 480px) {
  .ui-button, .ui-select__trigger, .ui-tabs__tab, .ui-segmented__option,
  .ui-select__option, .ui-data-table__sort {
    min-height: 44px;
  }
  .ui-button--icon { min-width: 44px; }
  .ui-check { min-height: 44px; padding-block: var(--space-2); }
  input[type="checkbox"], input[type="radio"] { min-width: 24px; min-height: 24px; accent-color: var(--accent); }
  .ui-data-table td:has(input[type="checkbox"]) { padding-block: var(--space-2); }
  .ui-data-table__link { display: inline-flex; align-items: center; min-height: 44px; }
  .ui-input, .ui-field :is(input:not([type="checkbox"], [type="radio"]), textarea),
  textarea.ui-input { font-size: 16px; min-height: 44px; }
  .ui-select__option { padding-block: var(--space-2); }
}

@media (max-width: 480px) {
  /* Empty/error tables have no rows to compare. Do not force their message
     into a desktop-width table that hides it beyond the phone viewport. */
  .ui-data-table table:has(.ui-data-table__message) { min-width: 0; }
  .ui-data-table table:has(.ui-data-table__message) :is(colgroup, thead) { display: none; }
  .ui-button { max-width: 100%; height: auto; min-height: 44px; white-space: normal; line-height: var(--leading-snug); padding-block: var(--space-2); }
  .ui-segmented { max-width: 100%; overflow-x: auto; }
  .ui-toolbar { flex-wrap: wrap; }
  .ui-toolbar > .ui-select, .ui-toolbar > .ui-toolbar__search { flex: 1 1 100%; min-width: 0; }
  .ui-data-table .ui-data-table__actions { position: static; box-shadow: none; }
  .ui-overlay__header { padding-inline: var(--space-4); }
  .ui-overlay__header > div { min-width: 0; }
  .ui-drawer-form__body, .ui-confirm__content { padding-inline: var(--space-4); }
  .ui-drawer-form__footer { flex-wrap: wrap; padding-inline: var(--space-4); padding-bottom: max(var(--space-4), env(safe-area-inset-bottom)); }
  .ui-drawer-form__footer > .ui-button { flex: 1 1 auto; }
  .ui-overlay__panel--drawer { height: 100dvh; bottom: auto; }
  .ui-overlay__body { min-width: 0; }
  .ui-overlay__panel { max-width: 100vw; }
  .ui-overlay__header { padding-top: max(var(--space-5), env(safe-area-inset-top)); }
}

/* ── Segmented radios ─────────────────────────────────────────────────── */
/* A radio group that reads as one segmented control: the input stays for
   the form and assistive tech, its label is the button. */
.ui-segmented__option:has(> input[type="radio"]) {
  position: relative;
  display: inline-flex;
  align-items: center;
}

/* The input covers its label, so a click (a person's or a test's) lands on
   the radio itself. */
.ui-segmented__option > input[type="radio"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.ui-segmented__option:has(> input:checked) {
  background: var(--bg-hover);
  color: var(--text);
}

.ui-segmented__option:has(> input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ── Audio playground ─────────────────────────────────────────────────── */
/* What to send on the left, what came back on the right. */
.ui-audio__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
}

.ui-audio__head h3 { margin: 0 0 var(--space-1); }
.ui-audio__chips { margin: 0; padding: 0; list-style: none; }

.ui-audio__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-6);
  align-items: start;
}

.ui-audio__inputs {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.ui-audio__result {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
  min-height: 14rem;
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
}

.ui-audio__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.ui-audio__actions > .ui-status-indicator { margin-left: auto; font-size: var(--text-12); }
.ui-audio__placeholder { margin: 0; color: var(--text-dim); font-size: var(--text-13); }

.ui-audio__transcript {
  flex: 1;
  margin: 0;
  color: var(--text);
  font: inherit;
  font-size: var(--text-13);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.ui-audio__result > audio { width: 100%; }
.ui-audio__facts { --facts-min: 8rem; }

/* The file input is the whole zone: click anywhere, or drop a file on it. */
.ui-audio__drop {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-height: 7rem;
  padding: var(--space-4);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  text-align: center;
  cursor: pointer;
}

.ui-audio__drop:hover,
.ui-audio__drop:focus-within { border-color: var(--accent); }

.ui-audio__drop > input[type="file"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.ui-audio__drop > strong { font-size: var(--text-13); overflow-wrap: anywhere; }

@container main (max-width: 900px) {
  .ui-audio__body { grid-template-columns: minmax(0, 1fr); }
}
