Ctrl K
ComunidadGuías…

src/ui/local.css

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/*
 * Local dashboard and setup (/local). Page layout only; components come from
 * relmio-ui.css. Use kit tokens, never raw colors. See DESIGN.md.
 */

/* Shell ------------------------------------------------------------------ */

.local-wizard .rm-split {
  padding-block: var(--rm-space-3);
}

.local-wizard .rm-split__content > .rm-panel {
  flex: 1 1 auto;
}

.local-wizard .rm-panel__header {
  padding-block: var(--rm-space-4) var(--rm-space-3);
}

.local-wizard .rm-panel__body {
  padding-bottom: var(--rm-space-4);
}

/* Headings receive focus from script after a view change; they are not
   interactive, so they show no focus ring. */
.local-wizard :is(h1, h2)[tabindex="-1"]:focus {
  outline: none;
}

.setup-form {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
}

/* Status tones for dashboard dots, badges and summary values. */
.rm-status__dot.state-healthy {
  background: var(--rm-success);
}

.rm-status__dot:is(.state-stopped, .state-partial, .state-stale) {
  background: var(--rm-warning);
}

.rm-status__dot.state-unavailable {
  background: var(--rm-danger);
}

.rm-status__dot.state-checking {
  background: var(--rm-accent);
  animation: rm-pulse 1.2s var(--rm-ease-in-out) infinite;
}

/* Starting is a normal, calm state: Docker's first health check is still due. */
.rm-status__dot.state-starting {
  background: var(--rm-accent);
}

.rm-badge.state-healthy {
  --rm-tone: var(--rm-success);
  --rm-tone-soft: var(--rm-success-soft);
  --rm-tone-line: var(--rm-success-line);
}

.rm-badge:is(.state-stopped, .state-partial, .state-stale) {
  --rm-tone: var(--rm-warning);
  --rm-tone-soft: var(--rm-warning-soft);
  --rm-tone-line: var(--rm-warning-line);
}

.rm-badge.state-unavailable {
  --rm-tone: var(--rm-danger);
  --rm-tone-soft: var(--rm-danger-soft);
  --rm-tone-line: var(--rm-danger-line);
}

.rm-badge:is(.state-checking, .state-starting) {
  --rm-tone: var(--rm-accent-ink);
  --rm-tone-soft: var(--rm-accent-soft);
  --rm-tone-line: var(--rm-accent-line);
}

/* Dashboard -------------------------------------------------------------- */

.dashboard-rail-actions {
  display: grid;
  gap: var(--rm-space-2);
  padding-top: var(--rm-space-4);
  border-top: 1px solid var(--rm-line);
}

.dashboard-hosting-link {
  justify-self: start;
  padding: var(--rm-space-1) var(--rm-space-3);
  font-size: var(--rm-text-md);
}

.dashboard-body {
  gap: var(--rm-space-3);
}

.dashboard-error:not([hidden]) {
  display: block;
}

.dashboard-section {
  display: flex;
  flex-direction: column;
  gap: var(--rm-space-3);
  min-height: 0;
}

.dashboard-section-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--rm-space-1) var(--rm-space-4);
}

.dashboard-environment {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--rm-space-3);
  padding: var(--rm-space-4);
  border: 1px solid var(--rm-line);
  border-radius: var(--rm-radius-lg);
  background: var(--rm-surface);
}

.dashboard-environment strong {
  font-weight: 650;
}

.dashboard-environment p {
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-md);
}

.dashboard-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  gap: var(--rm-space-3);
  margin: 0;
}

.dashboard-summary > div {
  display: grid;
  align-content: start;
  gap: var(--rm-space-1);
  padding: var(--rm-space-4);
  border: 1px solid var(--rm-line);
  border-radius: var(--rm-radius-lg);
  background: var(--rm-surface-muted);
}

.dashboard-summary dt {
  font-size: var(--rm-text-lg);
  font-weight: 650;
  line-height: var(--rm-leading-snug);
}

.dashboard-summary dt[data-state="healthy"] {
  color: var(--rm-success);
}

.dashboard-summary dt[data-state="starting"] {
  color: var(--rm-accent-ink);
}

.dashboard-summary dt:is([data-state="stopped"], [data-state="partial"], [data-state="stale"]) {
  color: var(--rm-warning);
}

.dashboard-summary dt[data-state="unavailable"] {
  color: var(--rm-danger);
}

.dashboard-summary dd {
  margin: 0;
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-sm);
}

.dashboard-empty {
  align-items: center;
}

.dashboard-resource-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  align-items: start;
  gap: var(--rm-space-4);
  min-height: 0;
}

.dashboard-service-list,
.dashboard-compact-list,
.dashboard-activity-list,
.dashboard-relay,
.check-list,
.no-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.dashboard-service-list {
  display: grid;
  gap: var(--rm-space-1);
}

/* A quick action moves below the name when the row is too narrow for both,
   so names are never painted over. */
.dashboard-service-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--rm-space-2);
  min-width: 0;
  padding: 0.125rem var(--rm-space-2) 0.125rem 0.125rem;
  border: 1px solid var(--rm-line);
  border-radius: var(--rm-radius-md);
  background: var(--rm-surface);
}

.dashboard-service-row:has(> .dashboard-service-select[aria-pressed="true"]) {
  border-color: var(--rm-accent);
  background: var(--rm-accent-soft);
}

.dashboard-service-select {
  display: grid;
  flex: 1 1 12rem;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--rm-space-3);
  min-width: 0;
  min-height: 2.75rem;
  padding: 0.3125rem var(--rm-space-2);
  border: 0;
  border-radius: calc(var(--rm-radius-md) - 2px);
  background: transparent;
  color: var(--rm-ink);
  text-align: start;
}

.dashboard-service-select:disabled {
  cursor: default;
}

.dashboard-service-copy {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-width: 0;
  overflow-wrap: anywhere;
}

.dashboard-service-copy strong {
  font-size: var(--rm-text-md);
  font-weight: 650;
}

.dashboard-service-copy small {
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-xs);
  line-height: 1.4;
}

/* A connection that is not installed takes one line: its name, then its state. */
.dashboard-service-row--compact .dashboard-service-select {
  min-height: 2rem;
  padding-block: 0.125rem;
}

.dashboard-service-row--compact .dashboard-service-copy {
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  column-gap: var(--rm-space-2);
}

.dashboard-service-row-actions {
  flex: none;
  margin-inline-start: auto;
}

.dashboard-open-n8n {
  flex: none;
  margin-inline-start: auto;
}

.dashboard-service-placeholder {
  min-height: 3rem;
  padding: var(--rm-space-3);
}

.dashboard-service-placeholder span {
  display: block;
  height: 0.625rem;
  border-radius: var(--rm-radius-pill);
  background: var(--rm-surface-sunken);
  /* The first inventory read pulses briefly, then rests; it ends within 5 seconds. */
  animation: rm-pulse 1.2s var(--rm-ease-in-out) 4;
}

.dashboard-service-placeholder span:first-child {
  width: 40%;
}

.dashboard-service-placeholder span:last-child {
  width: 70%;
}

.dashboard-service-detail {
  display: grid;
  align-content: start;
  gap: var(--rm-space-2);
  padding: var(--rm-space-4);
}

.dashboard-service-facts {
  grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr);
  gap: 0.25rem var(--rm-space-4);
  padding-block: var(--rm-space-2);
  border-block: 1px solid var(--rm-line);
  font-size: var(--rm-text-sm);
}

.dashboard-copyable-fact {
  display: flex;
  align-items: flex-start;
  gap: var(--rm-space-2);
}

.dashboard-copyable-fact code {
  flex: 1 1 auto;
  min-width: 0;
}

.dashboard-relay {
  display: grid;
  gap: var(--rm-space-1);
}

.dashboard-relay li {
  display: grid;
  grid-template-columns: auto max-content minmax(0, 1fr);
  align-items: baseline;
  gap: 0 var(--rm-space-2);
  font-size: var(--rm-text-sm);
  font-weight: 600;
}

.dashboard-relay .rm-status__dot {
  align-self: center;
}

.dashboard-relay small {
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-xs);
  font-weight: 400;
  text-align: end;
}

/* Eight services fit on every fit screen. Rows keep their full text and wrap
   when narrow; the list scrolls only when zoom leaves less room than that. */
@media (min-width: 64rem) and (min-height: 37.5rem) {
  .dashboard-section {
    flex: 1 1 auto;
  }

  .dashboard-resource-grid {
    flex: 1 1 auto;
    grid-template-rows: minmax(0, 1fr);
  }

  .dashboard-service-list {
    max-height: 100%;
    margin: -0.25rem;
    padding: 0.25rem;
    overflow: auto;
    overscroll-behavior: contain;
  }

  .dashboard-service-row {
    flex-wrap: nowrap;
  }
}

/* At 1024 px the list column is too narrow for a name and a quick action on
   one line, so rows keep the full name and the selected connection card
   holds the actions. Tighter card spacing keeps its URLs on one screen. */
@media (min-width: 64rem) and (max-width: 79.99rem) and (min-height: 37.5rem) {
  .dashboard-service-row-actions {
    display: none;
  }

  .dashboard-service-detail {
    gap: var(--rm-space-1);
    padding: var(--rm-space-3);
  }
}

.dashboard-service-actions {
  --rm-gap: var(--rm-space-2);
}

.dashboard-service-actions p {
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-sm);
}

.dashboard-compact-list,
.dashboard-activity-list {
  border: 1px solid var(--rm-line);
  border-radius: var(--rm-radius-lg);
  background: var(--rm-surface);
}

.dashboard-compact-list > li,
.dashboard-activity-list > li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--rm-space-3);
  padding: var(--rm-space-3) var(--rm-space-4);
  border-bottom: 1px solid var(--rm-line);
}

.dashboard-compact-list > li:last-child,
.dashboard-activity-list > li:last-child {
  border-bottom: 0;
}

.dashboard-compact-list span:not([class]) {
  display: grid;
  min-width: 0;
}

.dashboard-compact-list strong {
  font-size: var(--rm-text-md);
  font-weight: 650;
}

.dashboard-compact-list small {
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-sm);
}

.dashboard-compact-list .dashboard-open-n8n {
  justify-self: start;
  margin-inline-start: 0;
  font-size: var(--rm-text-sm);
}

.dashboard-activity-list > li {
  font-size: var(--rm-text-md);
}

.dashboard-activity-list time {
  color: var(--rm-ink-muted);
  font-family: var(--rm-font-mono);
  font-size: var(--rm-text-xs);
}

/* Setup rail ------------------------------------------------------------- */

.setup-intro {
  display: grid;
  justify-items: start;
  gap: var(--rm-space-1);
}

.setup-dashboard-return {
  margin-inline-start: calc(-1 * var(--rm-space-3));
}

.setup-progress .rm-stepper__link {
  cursor: default;
}

.setup-progress .rm-stepper__link:hover {
  background: transparent;
}

/* Status and safety notes follow the step panels in the DOM, so narrow
   screens show the step title and actions first. The blocking error leads the
   notes, so it sits right after the footer actions there. From 1024px they
   sit in the rail column under the stepper, as on /assistant. */
.setup-notes {
  display: flex;
  flex-direction: column;
  gap: var(--rm-space-3);
  min-width: 0;
}

@media (min-width: 64rem) {
  .setup-shell {
    grid-template-rows: auto minmax(0, 1fr);
    row-gap: var(--rm-space-3);
  }

  .setup-rail {
    grid-area: 1 / 1;
  }

  .setup-workspace {
    grid-area: 1 / 2 / 3 / 3;
  }

  /* The notes share the window-high rail with the stepper. An error longer
     than the room left, or an opened disclosure, scrolls inside the notes so
     the step panel and its footer actions stay put. The padding keeps the
     focused error's outline inside the scroll box. */
  .setup-notes {
    grid-area: 2 / 1;
    min-height: 0;
    margin: -0.25rem;
    padding: 0.25rem;
    overflow-y: auto;
  }

  /* While an operation runs, its progress card sits under the stepper and the
     notes move down one row, so the step title and stepper stay in view. */
  .setup-shell:has(> .operation-progress:not([hidden])) {
    grid-template-rows: auto auto minmax(0, 1fr);
  }

  .setup-shell > .operation-progress {
    grid-area: 2 / 1;
  }

  .setup-shell:has(> .operation-progress:not([hidden])) > .setup-workspace {
    grid-area: 1 / 2 / 4 / 3;
  }

  .setup-shell:has(> .operation-progress:not([hidden])) > .setup-notes {
    grid-area: 3 / 1;
  }
}

.setup-status {
  display: grid;
  gap: var(--rm-space-2);
  padding: var(--rm-space-3);
}

.docker-status {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 0.625rem;
}

.docker-status .rm-status__dot {
  margin-top: 0.4375rem;
}

#docker-indicator.ready {
  background: var(--rm-success);
}

.docker-status strong {
  font-size: var(--rm-text-md);
  font-weight: 650;
}

.docker-status p,
.global-message {
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-sm);
  line-height: 1.45;
}

.global-message {
  padding-top: var(--rm-space-2);
  border-top: 1px solid var(--rm-line);
  overflow-wrap: anywhere;
}

/* An empty status line stays in the page for screen readers but takes no room. */
.global-message:has(> :empty) {
  padding-top: 0;
  border-top: 0;
}

.setup-status:has(#global-message-text:empty) {
  gap: 0;
}

/* Management views skip the Docker check. With no message the card collapses. */
.setup-status:has(.docker-status[hidden]):has(#global-message-text:empty) {
  padding: 0;
  border: 0;
  background: none;
}

.global-error .rm-link {
  justify-self: start;
}

.setup-safety {
  display: grid;
  gap: var(--rm-space-1);
}

.setup-safety__fact {
  display: flex;
  gap: var(--rm-space-2);
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-sm);
  line-height: 1.45;
}

.setup-safety__fact .rm-icon {
  margin-top: 0.125rem;
  color: var(--rm-accent-ink);
}

.setup-safety__fact--warning .rm-icon {
  color: var(--rm-warning);
}

.setup-help > summary {
  min-height: 2rem;
  font-size: var(--rm-text-sm);
}

.setup-help strong {
  font-weight: inherit;
}

/* Step 1: choose --------------------------------------------------------- */

.choose-stage {
  display: flex;
  flex-direction: column;
  gap: var(--rm-space-3);
}

.target-picker {
  gap: var(--rm-space-3);
}

.main-connection-choices,
.advanced-connection-choices {
  --rm-grid-min: 17rem;
  --rm-gap: var(--rm-space-2);
}

.target-card {
  align-content: start;
  padding: 0.625rem 0.875rem;
}

.target-card:has(.rm-choice__input:disabled) {
  background: var(--rm-surface-muted);
}

.target-card .rm-choice__input:disabled {
  cursor: not-allowed;
}

.target-card .rm-choice__icon {
  width: 2.25rem;
  height: 2.25rem;
}

.target-card .rm-choice__title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.125rem var(--rm-space-2);
  font-size: 0.9375rem;
}

.target-card .rm-choice__text {
  font-size: var(--rm-text-sm);
}

.advanced-connection-choices .rm-choice {
  grid-template-columns: minmax(0, 1fr);
}

.advanced-connection-choices :is(.rm-choice__title, .rm-choice__text, .rm-choice__meta) {
  grid-column: 1;
}

.more-connections > summary {
  min-height: 2.5rem;
}

.more-connections .rm-disclosure__body {
  padding-inline-start: 0.875rem;
}

/* On a narrower fit screen (1024 to 1279 px) the main choices use three
   columns and drop their decorative icons, so each card keeps who it is for
   and what it needs in two rows. Eight choices with every description do not
   fit: while More connections is open, both grids use three columns and the
   main choices keep their titles and badges only. Connection details and
   limits still holds every description. */
@media (min-width: 64rem) and (max-width: 79.99rem) and (min-height: 37.5rem) {
  :is(.main-connection-choices, .advanced-connection-choices) {
    --rm-grid-min: 11rem;
  }

  .main-connection-choices .rm-choice {
    grid-template-columns: minmax(0, 1fr);
  }

  .main-connection-choices .rm-choice__icon {
    display: none;
  }

  .main-connection-choices :is(.rm-choice__title, .rm-choice__text, .rm-choice__meta) {
    grid-column: 1;
  }

  .target-picker:has(> #more-connections-and-tools[open]) .main-connection-choices :is(.rm-choice__text, .rm-choice__meta) {
    display: none;
  }

  .target-picker:has(> #more-connections-and-tools[open]) .target-card .rm-badge {
    white-space: normal;
  }
}

.choose-help {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--rm-space-6);
}

.choose-help > details[open] {
  flex-basis: 100%;
}

.local-route-context {
  display: flex;
  flex-wrap: wrap;
  gap: var(--rm-space-2) var(--rm-space-5);
}

/* Step 1: settings ------------------------------------------------------- */

.configure-columns {
  display: flex;
  flex-direction: column;
  gap: var(--rm-space-3);
}

/* Use the width for n8n companions and the new n8n stack, whose settings do
   not fit one column. Columns keep the DOM reading order. */
.configure-columns:has(> #n8n-sidecar-fields:not([hidden]), > #n8n-stack-fields:not([hidden])) {
  display: block;
  column-gap: var(--rm-space-6);
  columns: 2 16rem;
}

.configure-columns:has(> #n8n-sidecar-fields:not([hidden]), > #n8n-stack-fields:not([hidden])) :is(.route-summary, .target-guidance, .supergrok-n8n-reminder, .config-block) {
  margin-bottom: var(--rm-space-2);
  break-inside: avoid;
}

/* The account card uses the width: the account select beside its actions,
   then the state and sign-in rows across both columns. DOM order matches the
   visual order, so focus moves select, actions, then Refresh status. */
@media (min-width: 64rem) {
  #local-siwc {
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    align-items: start;
    gap: var(--rm-space-2) var(--rm-space-3);
  }

  #local-siwc > :not(.siwc-account, .siwc-actions) {
    grid-column: 1 / -1;
  }
}

.target-guidance {
  padding: 0.625rem 0.75rem;
  font-size: var(--rm-text-sm);
  line-height: 1.45;
}

.scope-note {
  display: flex;
  gap: var(--rm-space-2);
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-sm);
  line-height: 1.45;
}


body[data-current-step="1"] .setup-shell {
  padding-block: var(--rm-space-1);
}

body[data-current-step="1"] .setup-panel :is(.rm-panel__header, .rm-panel__footer) {
  padding-block: var(--rm-space-2);
}
.scope-note .rm-icon {
  margin-top: 0.125rem;
  color: var(--rm-accent-ink);
}

.scope-note strong {
  color: var(--rm-ink);
  font-weight: 650;
}

.route-summary {
  display: flex;
  align-items: center;
  gap: var(--rm-space-3);
  padding: var(--rm-space-1) var(--rm-space-1) var(--rm-space-1) var(--rm-space-3);
  border: 1px solid var(--rm-line);
  border-radius: var(--rm-radius-md);
  background: var(--rm-surface-muted);
}

.route-summary > .rm-icon {
  color: var(--rm-accent-ink);
}

.route-summary__text {
  display: grid;
  flex: 1 1 auto;
  min-width: 0;
  line-height: 1.3;
}

.section-heading {
  display: grid;
  gap: var(--rm-space-1);
}

.sidecar-status-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--rm-space-2) var(--rm-space-3);
}

.sidecar-status-row p {
  flex: 1 1 12rem;
}

.detected-integration-actions {
  --rm-gap: var(--rm-space-2);
}

.managed-companion-edit > summary {
  font-size: var(--rm-text-md);
}

.managed-companion-edit .rm-disclosure__body {
  gap: var(--rm-space-3);
}

.managed-companion-edit-actions,
.sidecar-removal-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--rm-space-2) var(--rm-space-3);
}

.managed-companion-edit-actions p,
.sidecar-removal-actions p {
  flex: 1 1 14rem;
  color: var(--rm-ink-muted);
}

.managed-companion-edit-review {
  display: grid;
  gap: var(--rm-space-3);
}

.check-row {
  font-size: var(--rm-text-md);
}

.ngrok-checklist ol {
  display: grid;
  gap: var(--rm-space-1);
  margin: 0;
  padding-inline-start: 1.125rem;
}

.stack-fields {
  --rm-field-min: 9rem;
  gap: var(--rm-space-3);
}

.stack-field-wide {
  grid-column: 1 / -1;
}

/* Step 2: review --------------------------------------------------------- */

.panel-columns {
  column-gap: var(--rm-space-6);
  columns: 2 16rem;
}

.panel-columns > * {
  margin-bottom: var(--rm-space-1);
  break-inside: avoid;
}

/* The review packs its facts two per row and gives the plan lists the full
   width, so the longest n8n plan fits a 1024 px window. */
@media (min-width: 64rem) {
  .review-columns {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--rm-space-2) var(--rm-space-4);
  }

  .review-columns > * {
    margin-bottom: 0;
  }

  .review-columns > :is(.local-provider-context, .review-details, .policy-note, .review-actions, .rm-notice) {
    grid-column: 1 / -1;
  }

  /* The model plan has two disclosures; they share one row. */
  .review-columns:has(> .model-review-provenance:not([hidden])) > .review-actions {
    grid-column: auto;
  }

  .review-columns .review-details {
    grid-template-columns: 1fr 1fr;
    gap: 0.375rem var(--rm-space-6);
  }

  .review-columns .review-details > div:not([hidden]) {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    column-gap: var(--rm-space-3);
    align-items: baseline;
  }

  .review-columns .review-details > div[hidden] {
    display: none;
  }

  .review-columns .review-list {
    gap: 0.125rem;
  }

  .review-columns :is(.check-list, .no-list) {
    font-size: var(--rm-text-sm);
    line-height: 1.35;
  }

  .review-actions-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--rm-space-3) var(--rm-space-4);
  }
}



.local-provider-context:empty,
.policy-note:empty {
  display: none;
}

.result-list {
  grid-template-columns: minmax(6.5rem, 9.5rem) minmax(0, 1fr);
  gap: 0.375rem var(--rm-space-4);
}

.result-list dd code {
  font-size: var(--rm-text-sm);
}

.model-box {
  display: grid;
  gap: var(--rm-space-2);
}

.review-list {
  display: grid;
  gap: var(--rm-space-1);
}

.check-list,
.no-list {
  display: grid;
  gap: 0.125rem;
  font-size: var(--rm-text-md);
  line-height: 1.35;
}

.check-list li,
.no-list li {
  position: relative;
  padding-inline-start: 1.5rem;
}

.check-list li::before,
.no-list li::before {
  position: absolute;
  top: 0.15em;
  left: 0;
  width: 1rem;
  height: 1rem;
  content: "";
  -webkit-mask: var(--rm-icon-check) center / contain no-repeat;
  mask: var(--rm-icon-check) center / contain no-repeat;
}

.check-list li::before {
  background-color: var(--rm-success);
}

.no-list li::before {
  background-color: var(--rm-danger);
  -webkit-mask-image: var(--rm-icon-x);
  mask-image: var(--rm-icon-x);
}

.policy-note {
  display: grid;
  gap: 0.125rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--rm-warning-line);
  border-radius: var(--rm-radius-md);
  background: var(--rm-warning-soft);
  font-size: var(--rm-text-md);
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.policy-note strong {
  font-weight: 650;
}

.policy-note p {
  color: var(--rm-ink-muted);
}

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

.approval .rm-check {
  font-size: var(--rm-text-sm);
}

#installed-images a {
  overflow-wrap: anywhere;
}

/* Step 3: install -------------------------------------------------------- */

.stack-secrets {
  --rm-field-min: 15rem;
}

.credential-field-actions {
  --rm-gap: var(--rm-space-2);
}

/* Step 4: ready ---------------------------------------------------------- */

.local-wizard .success-panel .rm-panel__header {
  padding-block: var(--rm-space-3);
}

.success-heading {
  flex-wrap: nowrap;
  align-items: center;
}

.success-mark {
  display: grid;
  flex: none;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--rm-success-line);
  border-radius: 50%;
  background: var(--rm-success-soft);
  color: var(--rm-success);
}

/* The mark confirms an install that just finished; management views never show it. */
.success-mark {
  animation: local-success-in var(--rm-duration-slow) var(--rm-ease);
}

@keyframes local-success-in {
  from {
    opacity: 0;
    transform: scale(0.8);
  }
}

.result-value {
  display: flex;
  align-items: flex-start;
  gap: var(--rm-space-2);
  min-width: 0;
}

.result-value > code,
.result-value > pre {
  flex: 1 1 auto;
  min-width: 0;
}

.result-settings-value pre {
  margin: 0;
  padding: var(--rm-space-2) var(--rm-space-3);
  border: 1px solid var(--rm-line);
  border-radius: var(--rm-radius-sm);
  background: var(--rm-surface-muted);
  font-size: var(--rm-text-sm);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.ready-settings:has(#result-n8n-settings-row[hidden]) {
  display: none;
}

.ready-optional:has(> [hidden]) {
  display: none;
}

.ready-optional:has(#n8n-stack-removal[hidden]) {
  display: none;
}

.stack-open {
  align-items: baseline;
  gap: var(--rm-space-2) var(--rm-space-4);
}

.stack-open p {
  margin: 0;
}

.stack-addon-actions {
  --rm-gap: var(--rm-space-2);
  margin-top: var(--rm-space-2);
}

.ready-columns .result-list {
  font-size: var(--rm-text-sm);
  line-height: 1.3;
}

.ready-safety__list {
  display: grid;
  gap: var(--rm-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ready-safety__list > li {
  display: grid;
  gap: 0.125rem;
}

.ready-safety__list p {
  margin: 0;
}

.ready-safety .policy-note {
  padding: 0;
  border: 0;
  background: none;
  font-size: inherit;
  line-height: inherit;
}

.ready-safety .policy-note p {
  color: inherit;
}

.ready-safety:not(:has(li:not([hidden]))) {
  display: none;
}

@media (min-width: 64rem) {
  .ready-columns > #install-result-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--rm-space-2) var(--rm-space-4);
  }

  .ready-columns > #install-result-list > div:not([hidden]) {
    display: grid;
    align-content: start;
    gap: 0.125rem;
    min-width: 0;
  }

  .ready-columns > #install-result-list > div[hidden] {
    display: none;
  }

  .ready-columns > #install-result-list :is(dd, code) {
    overflow-wrap: anywhere;
    font-family: var(--rm-font-mono);
  }

  .ready-columns:not(:has(#n8n-stack-removal:not([hidden]))) {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: var(--rm-space-2) var(--rm-space-4);
  }

  .ready-columns:not(:has(#n8n-stack-removal:not([hidden]))) > * {
    margin-bottom: 0;
  }
  .ready-columns:not(:has(#n8n-stack-removal:not([hidden]))) > :is(#install-result-list, #codex-login) {
    grid-column: 1 / -1;
  }
  .ready-columns > #n8n-claude-management {
    grid-column: 1 / -1;
  }
  /* With a ChatGPT account card, the key safety notes sit beside it instead
     of taking their own row. */
  .ready-columns:not(:has(#n8n-stack-removal:not([hidden]))):not(:has(> #installed-siwc-models:not([hidden]))) > .ready-safety {
    grid-column: 1 / -1;
  }
  .ready-columns:not(:has(#n8n-stack-removal:not([hidden]))) .ready-safety__list {
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    align-items: start;
  }

  .ready-columns:has(#n8n-stack-addons:not([hidden])) {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
    gap: var(--rm-space-2) var(--rm-space-4);
  }

  .ready-columns:has(#n8n-stack-addons:not([hidden])) > :is(
    #n8n-stack-open, #install-result-list, #n8n-stack-addons, .ready-safety
  ) {
    grid-column: 1 / -1;
    margin-bottom: 0;
  }
}

/* The step caption and the provider context share the eyebrow line and wrap
   when the header is narrow. */
.success-eyebrows {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--rm-space-1) var(--rm-space-4);
}

.success-eyebrows > #done-provider-context {
  font-size: var(--rm-text-xs);
  line-height: 1.2;
}

body[data-current-step="4"] .setup-shell {
  padding-block: var(--rm-space-1);
}

.success-panel .rm-panel__footer {
  padding-block: 0;
}


.success-mark {
  width: 2.25rem;
  height: 2.25rem;
}

.ready-safety__list {
  font-size: var(--rm-text-sm);
  line-height: 1.35;
}

@media (max-width: 68rem) {
  .ready-columns > #install-result-list > :is(
    #result-endpoint-row,
    #result-searxng-row,
    #result-sandbox-key-row
  ):not([hidden]) {
    grid-column: 1 / -1;
  }

  .ready-columns > #install-result-list,
  .ready-safety__list {
    font-size: var(--rm-text-xs);
    line-height: 1.3;
  }

  .local-wizard .success-panel .rm-panel__header {
    padding-block: var(--rm-space-2);
  }

  .ready-safety {
    padding: var(--rm-space-1) var(--rm-space-2);
  }

  .ready-columns > #install-result-list {
    gap: 0 var(--rm-space-3);
  }

  .configure-columns:has(> #n8n-sidecar-fields:not([hidden])) :is(.rm-callout, .config-block, .rm-field__hint, .scope-note) {
    font-size: var(--rm-text-xs);
    line-height: 1.3;
  }

  .configure-columns:has(> #n8n-sidecar-fields:not([hidden])) :is(.route-summary, .target-guidance, .config-block) {
    margin-bottom: var(--rm-space-1);
  }

  .ready-columns {
    gap: var(--rm-space-1) var(--rm-space-3);
  }

  .codex-login {
    padding: var(--rm-space-2);
    font-size: var(--rm-text-xs);
    line-height: 1.3;
  }
}

.codex-login,
.n8n-sidecar-removal,
.local-model-management {
  display: grid;
  justify-items: start;
  gap: var(--rm-space-1);
}

/* Installed account controls keep their natural width inside the disclosure. */
#local-siwc-owner > .rm-disclosure__body {
  justify-items: start;
}

.success-panel :is(.rm-callout, .rm-card--compact) {
  padding: var(--rm-space-2) var(--rm-space-3);
}

@media (max-width: 68rem) {
  .success-panel :is(.codex-login, .ready-safety) {
    padding: var(--rm-space-1) var(--rm-space-2);
    font-size: var(--rm-text-xs);
    line-height: 1.25;
  }

  .success-panel .codex-login :is(h2, h3, .rm-h3) {
    font-size: var(--rm-text-sm);
    line-height: 1.2;
  }
}

.success-panel .panel-columns > * {
  margin-bottom: 0;
}


.n8n-sidecar-removal > *,
.local-model-management > * {
  justify-self: stretch;
}

/* While a model action review is open, it replaces the Ready settings and the
   Refresh/Review buttons; Cancel brings them back. */
.local-model-management:has(> #local-model-action-review:not([hidden])) > :is(#local-model-settings, .actions) {
  display: none;
}

.removal-danger {
  color: var(--rm-danger);
}

.device-code-result {
  display: grid;
  justify-items: start;
  gap: var(--rm-space-2);
}

.device-code-step {
  display: grid;
  gap: var(--rm-space-1);
}

.device-code-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--rm-space-2);
}

/* While the device code is on screen, the ready view keeps only the endpoint,
   key safety and sign-in. Testing and rotation return when sign-in ends. */
.ready-columns:has(#device-code-step:not([hidden])) > :is(#chat-tester, #credential-rotation-note) {
  display: none;
}

.device-code-row code {
  padding: var(--rm-space-1) var(--rm-space-3);
  font-size: var(--rm-text-lg);
  letter-spacing: 0.08em;
}

/* Chat tester */
.chat-tester-body {
  gap: var(--rm-space-2);
  padding-inline-start: 0.875rem;
}

/* The tester is an ordinary disclosure in the ready flow. Opened, it takes the
   full width and the panel body scrolls (DESIGN.md disclosure exception). */
@media (min-width: 64rem) {
  .ready-columns > #chat-tester[open] {
    grid-column: 1 / -1;
  }
}

.chat-tester-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--rm-space-2);
}

.chat-tester-route {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--rm-space-1) var(--rm-space-2);
}

.chat-tester-route strong {
  color: var(--rm-ink);
}

.chat-tester-form,
.chat-tester-message-form {
  display: grid;
  justify-items: start;
  gap: var(--rm-space-3);
}

.chat-tester-form > fieldset,
.chat-tester-message-form > .rm-field {
  justify-self: stretch;
}

.chat-tester-form legend {
  font-size: var(--rm-text-md);
  font-weight: 650;
}

.chat-tester-message-actions {
  --rm-gap: var(--rm-space-2);
}

.chat-tester-status {
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-sm);
  overflow-wrap: anywhere;
}

.chat-tester-error:not([hidden]) {
  display: block;
}

.chat-tester-transcript {
  display: grid;
  gap: var(--rm-space-2);
  max-height: 16rem;
  margin: 0;
  padding: 0;
  overflow: auto;
  list-style: none;
}

.chat-tester-transcript:empty {
  display: none;
}

.chat-tester-turn {
  max-width: min(100%, 46rem);
  padding: var(--rm-space-2) var(--rm-space-3);
  border: 1px solid var(--rm-line);
  border-radius: var(--rm-radius-md);
  background: var(--rm-surface);
  font-size: var(--rm-text-md);
}

.chat-tester-turn-assistant {
  border-color: var(--rm-accent-line);
  background: var(--rm-accent-soft);
}

.chat-tester-turn-incomplete {
  border-style: dashed;
  border-color: var(--rm-warning-line);
  background: var(--rm-warning-soft);
}

.chat-tester-turn strong {
  display: block;
  margin-bottom: 0.125rem;
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-xs);
  font-weight: 650;
}

.chat-tester-turn-incomplete strong {
  color: var(--rm-warning);
}

.chat-tester-turn p {
  min-height: 1.5em;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.chat-tester-turn-waiting p {
  display: inline-flex;
  align-items: center;
}

.chat-tester-turn-waiting p::before {
  flex: none;
  width: 1.5rem;
  height: 2px;
  border-radius: 1px;
  background: var(--rm-line-strong);
  content: "";
  animation: chat-tester-waiting 1.3s var(--rm-ease-in-out) infinite;
}

.chat-tester-stream-cursor::after {
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-inline-start: 0.125rem;
  background: var(--rm-accent);
  content: "";
  vertical-align: text-bottom;
  animation: chat-tester-streaming 1.3s var(--rm-ease-in-out) infinite;
}

@keyframes chat-tester-waiting {
  50% {
    opacity: 0.35;
  }
}

@keyframes chat-tester-streaming {
  50% {
    opacity: 0.35;
  }
}

/* Operation progress. From 1024 px it sits in the rail under the stepper (see
   the setup shell grid above). Narrower windows: a dock that takes the place of
   the step's sticky footer, whose actions are locked while it shows. It follows
   the step in the page flow, so its height is part of the layout, and it sticks
   to the bottom like the footer it replaces. Kit scroll padding keeps focus
   clear of it. */
@media (max-width: 63.99rem) {
  .operation-progress {
    position: sticky;
    z-index: 1;
    bottom: 0;
    order: 1;
    margin-inline: calc(-1 * var(--rm-gutter));
  }

  .setup-shell:has(> .operation-progress:not([hidden])) .setup-panel .rm-panel__footer {
    display: none;
  }

  .operation-progress .install-progress {
    gap: var(--rm-space-2);
    padding: var(--rm-space-3) var(--rm-gutter) calc(var(--rm-space-3) + env(safe-area-inset-bottom, 0px));
    border-width: 1px 0 0;
    border-radius: 0;
    background: var(--rm-surface);
    box-shadow: none;
  }

  /* The phase line names the work; the heading stays for screen readers. */
  .operation-progress .install-progress-heading h2 {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .operation-progress .install-progress-phase {
    color: var(--rm-ink);
    font-weight: 600;
  }

  .operation-progress .install-progress-elapsed {
    grid-auto-flow: column;
    align-items: baseline;
    gap: var(--rm-space-1);
  }

  .operation-progress .install-progress-note {
    font-size: var(--rm-text-xs);
    line-height: 1.35;
  }
}

.install-progress {
  display: grid;
  gap: var(--rm-space-2);
}

.install-progress:focus {
  outline: none;
}

.install-progress:focus-visible {
  outline: 3px solid var(--rm-focus);
  outline-offset: 2px;
}

.install-progress-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--rm-space-3);
}

.install-progress-elapsed {
  display: grid;
  justify-items: end;
  color: var(--rm-ink-muted);
  font-size: var(--rm-text-xs);
}

.install-progress-elapsed time {
  color: var(--rm-ink);
  font-family: var(--rm-font-mono);
  font-size: var(--rm-text-md);
  font-variant-numeric: tabular-nums;
}

/* Narrow and medium windows ---------------------------------------------- */

@media (max-width: 63.99rem) {
  .dashboard-nav-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--rm-space-1);
  }

  .dashboard-nav-list .rm-sidebar__link {
    width: auto;
  }

  .dashboard-rail-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    padding-top: var(--rm-space-3);
  }

  /* The rail sits above the panel here; keep it short so the step title and
     first choice reach the first screen. */
  .setup-rail {
    gap: var(--rm-space-3);
  }

  .setup-safety {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--rm-space-5);
  }

  .setup-safety__fact,
  .setup-safety > details[open] {
    flex-basis: 100%;
  }
}

@media (max-width: 52rem) {
  .dashboard-resource-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 30rem) {
  .dashboard-environment {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .dashboard-environment > .rm-badge {
    grid-column: 2;
    justify-self: start;
  }

  .dashboard-relay {
    grid-template-columns: minmax(0, 1fr);
  }

  .result-list {
    grid-template-columns: minmax(0, 1fr);
  }

  .success-heading {
    flex-wrap: wrap;
  }
}

/* Claude for n8n --------------------------------------------------------- */

/* The review has two stages: the owner answers, then the plan. */
.claude-review {
  display: grid;
  align-content: start;
  gap: var(--rm-space-3);
}

.claude-review__checks {
  display: grid;
  gap: var(--rm-space-2);
}

.claude-review > .rm-link {
  justify-self: start;
}

/* The Claude view stacks the card and its two disclosures. Closed, the
   disclosures share a row at desktop widths, so the view keeps one screen.
   Once one is open, each takes the full width (DESIGN.md disclosure
   exception). */
.claude-view {
  display: grid;
  gap: var(--rm-space-2);
}

@media (min-width: 64rem) {
  .claude-view {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .claude-view > .claude-card,
  .claude-view:has(> details[open]) > details {
    grid-column: 1 / -1;
  }
}

/* Every part of the management card has its own row and gap, so the guide's
   pointer never sits on the sign-in sentence or the command. */
.claude-card {
  display: grid;
  gap: var(--rm-space-2);
}

.claude-card > .rm-terminal {
  box-shadow: none;
}

.claude-card .rm-terminal__body {
  padding-block: 0.5rem;
}

.claude-card__check {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--rm-space-2) var(--rm-space-3);
}

.claude-card__check > p {
  flex: 1 1 14rem;
}

#claude-runtime-help code {
  overflow-wrap: anywhere;
}

/* Discovery reads Docker: a short pulse marks the wait, then rests. */
#n8n-discovery-status[data-loading]::before {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-inline-end: var(--rm-space-2);
  border-radius: var(--rm-radius-pill);
  background: var(--rm-accent);
  content: "";
  vertical-align: 0.0625rem;
  animation: rm-pulse 1.2s var(--rm-ease-in-out) 4;
}

@media (forced-colors: active) {
  /* The selected connection keeps an inset Highlight frame; the focus ring stays separate. */
  .dashboard-service-row:has(> .dashboard-service-select[aria-pressed="true"]) {
    outline: 2px solid Highlight;
    outline-offset: -2px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rm-status__dot.state-checking,
  .dashboard-service-placeholder span,
  #n8n-discovery-status[data-loading]::before,
  .success-mark {
    animation: none;
  }

  .chat-tester-turn-waiting p::before,
  .chat-tester-stream-cursor::after {
    animation: none;
  }
}

/* From 1024 to 1279px the review facts use tighter gaps, so long names
   wrap less and the plan stays on one screen. */
@media (min-width: 64rem) and (max-width: 79.99rem) {
  .review-columns .review-details {
    gap: 0.25rem var(--rm-space-4);
  }

  .review-columns .review-details > div:not([hidden]) {
    column-gap: var(--rm-space-2);
  }

  /* The rail stepper beside the panel already marks the review step. */
  .setup-panel[data-step="2"] .rm-panel__heading > .rm-eyebrow {
    display: none;
  }

  .review-columns {
    row-gap: var(--rm-space-1);
  }
}